zoukankan      html  css  js  c++  java
  • noi.ac NOIP2018 全国热身赛 第二场 T3 color

    【题解】

      我们可以发现每次修改之后叶子结点到根的路径最多分为两段:一段白色或者黑色,上面接另一段灰色的。二分+倍增找到分界点,然后更新答案即可。

      check的时候只需要判断当前节点对应的叶子结点的区间是否全部为同一种颜色,用树状数组维护所有叶子节点组成的序列的状态即可。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<cmath>
     6 #define LL long long
     7 #define rg register
     8 #define N 200010
     9 using namespace std;
    10 int n,m,rt,cnt,ans0,ans1,l[N],r[N],t[N],col[N],dep[N],pos[N],lea[N],p[N][25];
    11 vector<int>son[N];
    12 inline int read(){
    13     int k=0,f=1; char c=getchar();
    14     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    15     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    16     return k*f;
    17 }
    18 void dfs(int x){
    19     dep[x]=dep[p[x][0]]+1;
    20     if(!son[x].size()){
    21         if(col[x]==1) ans1++;else ans0++;
    22         pos[x]=l[x]=r[x]=++cnt; lea[cnt]=x; return;
    23     }
    24     int cnt0=0,cnt1=0;
    25     for(rg int i=0;i<(int)son[x].size();i++){
    26         dfs(son[x][i]);
    27         l[x]=min(l[x],l[son[x][i]]); r[x]=max(r[x],r[son[x][i]]);
    28         if(!col[son[x][i]]) cnt0++;
    29         else if(col[son[x][i]]==1) cnt1++;
    30     }
    31     if(cnt0==(int)son[x].size()) col[x]=0,ans0++;
    32     else if(cnt1==(int)son[x].size()) col[x]=1,ans1++;
    33     else col[x]=2;
    34 }
    35 inline void add(int x,int y){for(;x<=n;x+=x&-x)t[x]+=y;}
    36 inline int query(int x){int ret=0;for(;x;x-=x&-x)ret+=t[x];return ret;}
    37 int main(){
    38     memset(l,0x7f,sizeof(l));
    39     memset(r,0,sizeof(r));
    40     n=read(); m=read();
    41     for(rg int i=1;i<=n;i++){
    42         son[p[i][0]=read()].push_back(i);
    43         if(!p[i][0]) rt=i;
    44     }
    45     for(rg int i=1;i<=n;i++) col[i]=read();
    46     dfs(rt);
    47 //    for(rg int i=1;i<=n;i++) printf("[%d %d]
    ",l[i],r[i]);
    48     for(rg int j=1;j<21;j++)
    49         for(rg int i=1;i<=n;i++) p[i][j]=p[p[i][j-1]][j-1];
    50     for(rg int i=1;i<=n;i++) add(i,col[lea[i]]);
    51 //    printf("%d %d %d
    ",ans1,ans0,n-ans0-ans1);
    52     while(m--){
    53         int x=read(),y=x;
    54         if(col[x]){
    55             for(rg int i=20;i>=0;i--)if(p[y][i]){
    56                 int pa=p[y][i],sum=query(r[pa])-query(l[pa]-1);
    57                 if(sum==r[pa]-l[pa]+1) y=pa;
    58             }
    59             ans1-=dep[x]-dep[y]+1;
    60 //            printf("y=%d
    ",y);
    61             add(pos[x],-1); y=x; 
    62             for(rg int i=20;i>=0;i--)if(p[y][i]){
    63                 int pa=p[y][i],sum=query(r[pa])-query(l[pa]-1);
    64                 if(sum==0) y=pa;
    65             }
    66             ans0+=dep[x]-dep[y]+1; 
    67 //            printf("y=%d
    ",y);
    68         }
    69         else{
    70             for(rg int i=20;i>=0;i--)if(p[y][i]){
    71                 int pa=p[y][i],sum=query(r[pa])-query(l[pa]-1);
    72                 if(sum==0) y=pa;
    73             }
    74             ans0-=dep[x]-dep[y]+1;
    75 //            printf("y=%d
    ",y);
    76             add(pos[x],1); y=x;
    77             for(rg int i=20;i>=0;i--)if(p[y][i]){
    78                 int pa=p[y][i],sum=query(r[pa])-query(l[pa]-1);
    79                 if(sum==r[pa]-l[pa]+1) y=pa;
    80             }
    81             ans1+=dep[x]-dep[y]+1;
    82 //            printf("y=%d
    ",y); 
    83         }
    84         col[x]^=1;
    85         printf("%d %d %d
    ",ans1,ans0,n-ans0-ans1);
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    EXT2
    Ext.DomQuery

    spring.net+nhibernate
    网址
    一句代码就解决一个开发中常见的小bug....
    Swift 已经正式开源了! 你了解到了吗?
    [知识点随笔] UIView--transform 属性
    懒加载(延迟加载)之后,在使用数据过程中容易出现的bug
    java设计模式
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9836687.html
Copyright © 2011-2022 走看看