zoukankan      html  css  js  c++  java
  • [POI2014]Supercomputer

    题目大意:
      给定一个$n(nle10^6)$个结点的有根树,从根结点开始染色。每次可以染和已染色结点相邻的任意$k$个结点。$q(qle10^6)$组询问,每次给定$k$,问至少需要染几次?

    思路:
      显然$ans=maxleft{i+leftlceilfrac{sum[i]}k ight ceil ight}$。而这样做是$O(nq)$的,观察到原式$=leftlceilfrac{maxleft{ki+sum[i] ight}}k ight ceil$。$max$中是关于$k$的一次函数,考虑使用斜率优化,做到$O(n+q)$。

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<algorithm>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int N=1e6+1;
    13 int k[N],sum[N],h[N],head=1,tail,sz,max,ans[N],q[N];
    14 struct Edge {
    15     int to,next;
    16 };
    17 Edge e[N<<1];
    18 inline void add_edge(const int &u,const int &v) {
    19     e[++sz]=(Edge){v,h[u]};h[u]=sz;
    20 }
    21 void dfs(const int &x,const int &dep) {
    22     sum[dep]++;
    23     max=std::max(max,dep);
    24     for(int i=h[x];i;i=e[i].next) {
    25         const int &y=e[i].to;
    26         dfs(y,dep+1);
    27     }
    28 }
    29 inline double calc (const int &i,const int &j) {
    30     return (double)(sum[j]-sum[i])/(i-j);
    31 }
    32 int main() {
    33     const int n=getint();
    34     for(register int i=0;i<=k[0];i++) k[i]=getint();
    35     for(register int i=2;i<=n;i++) {
    36         add_edge(getint(),i);
    37     }
    38     dfs(1,0);
    39     for(register int i=max;~i;i--) sum[i]+=sum[i+1];
    40     for(register int i=max;~i;i--) {
    41         while(head<tail&&calc(q[tail-1],q[tail])<=calc(q[tail],i)) tail--;
    42         q[++tail]=i;
    43     }
    44     for(register int i=n;i;i--) {
    45         while(head<tail&&calc(q[head],q[head+1])>=i) head++;
    46         ans[i]=q[head]+ceil((double)sum[q[head]]/i);
    47     }
    48     for(register int i=1;i<=k[0];i++) {
    49         printf("%d%c",k[i]<=n?ans[k[i]]:max+1," 
    "[i==k[0]]);
    50     }
    51     return 0;
    52 }
  • 相关阅读:
    2020/10/25助教一周小结(第八周)
    2020/10/18助教一周小结(第七周)
    2020/10/11助教一周小结(第六周)
    2020/10/05助教一周小结(第五周)
    2020/09/27助教一周小结(第四周)
    第三次作业总结
    第二次作业总结
    2020-11-08 助教一周小结(第十周)
    2020-11-01 助教一周小结(第九周)
    2020-10-25 助教一周小结(第八周)
  • 原文地址:https://www.cnblogs.com/skylee03/p/8662768.html
Copyright © 2011-2022 走看看