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 }
  • 相关阅读:
    【随机过程】马尔可夫链(2)
    【机器学习】机器学习中的各种相似性、距离度量
    【机器学习】机器学习中的各种相似性、距离度量
    嵌入式开发之8127---DM8127如何利用EDMA搬移数据
    嵌入式开发之8127---核心板原理图
    8148和8127中的ezsdk和dvrsdk
    dm385和8127的区别
    Appro DM8127 IPNC 挂载NFS遇到的问题及解决
    嵌入式开发之cmos---前端采集aptina cmos
    阶段1 语言基础+高级_1-3-Java语言高级_09-基础加强_第2节 反射_11_反射_案例
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9836687.html
Copyright © 2011-2022 走看看