题意:给你一棵树。两种操作:1.将x点到根的链全部修改成1颜色。
2.将x点及其子树全部修改成0颜色。每次询问修改了多少个点的颜色。
标程:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=400005; 4 int cnt,head[N],q,size[N],Dfn,fa[N],in[N],out[N],top[N],x,n,sum[N],tag[N]; 5 char s[15]; 6 struct node{int to,next;}num[N]; 7 void add(int x,int y) 8 {num[++cnt].to=y;num[cnt].next=head[x];head[x]=cnt;} 9 void dfs(int x) 10 { 11 size[x]=1; 12 for (int i=head[x];i;i=num[i].next) 13 if (num[i].to!=fa[x]) 14 { 15 dfs(num[i].to); 16 size[x]+=size[num[i].to]; 17 } 18 } 19 void dfs1(int x) 20 { 21 in[x]=++Dfn; 22 if (!top[x]) top[x]=x; 23 int t=0; 24 for (int i=head[x];i;i=num[i].next) 25 if (num[i].to!=fa[x]&&size[num[i].to]>size[t]) t=num[i].to; 26 if (t) top[t]=top[x],dfs1(t); 27 for (int i=head[x];i;i=num[i].next) 28 if (num[i].to!=fa[x]&&num[i].to!=t) dfs1(num[i].to); 29 out[x]=Dfn; 30 } 31 void down(int k,int l,int r) 32 { 33 if (tag[k]==1) 34 { 35 tag[k<<1]=1;tag[k<<1|1]=1; 36 sum[k<<1]=0;sum[k<<1|1]=0; 37 tag[k]=0; 38 }else 39 if (tag[k]==2) 40 { 41 tag[k<<1]=2;tag[k<<1|1]=2;int mid=(l+r)>>1; 42 sum[k<<1]=mid-l+1;sum[k<<1|1]=r-mid; 43 tag[k]=0; 44 } 45 } 46 int get_sum(int k,int l,int r,int L,int R,int op) 47 { 48 if (L<=l&&r<=R) 49 { 50 int t=sum[k]; 51 if (!op) {sum[k]=0;tag[k]=1;return t;} 52 else {sum[k]=r-l+1;tag[k]=2;return (r-l+1)-t;} 53 } 54 int mid=(l+r)>>1,tmp=0;down(k,l,r); 55 if (L<=mid) tmp+=get_sum(k<<1,l,mid,L,R,op); 56 if (R>mid) tmp+=get_sum(k<<1|1,mid+1,r,L,R,op); 57 sum[k]=sum[k<<1]+sum[k<<1|1]; 58 return tmp; 59 } 60 int qry(int x,int y) 61 { 62 int ans=0; 63 for (;top[x]!=top[y];x=fa[top[x]]) 64 { 65 if (in[x]<in[y]) swap(x,y); 66 ans+=get_sum(1,1,n,in[top[x]],in[x],1); 67 } 68 if (in[x]>in[y]) swap(x,y); 69 ans+=get_sum(1,1,n,in[x],in[y],1); 70 return ans; 71 } 72 int main() 73 { 74 scanf("%d",&n); 75 for (int i=2;i<=n;i++) scanf("%d",&fa[i]),add(++fa[i],i); 76 dfs(1);dfs1(1); 77 scanf("%d",&q); 78 while (q--) 79 { 80 scanf("%s%d",s,&x);x++; 81 if (s[0]=='i') printf("%d ",qry(1,x)); 82 else printf("%d ",get_sum(1,1,n,in[x],out[x],0)); 83 } 84 return 0; 85 }
易错点:1.注意标记会叠加,用一个标记数组,不要分两个。
题解:树链剖分+线段树
板子题吧。dfs序维护一下,再打个标记就好。