bzoj4196 [Noi2015]软件包管理器 树链剖分+线段树
先把树剖分了(又是dfs1、dfs2),然后区间求和、区间覆盖即可
难得的1A好(shui)题
——写了那么多题,终于有一道是1A的了,加上上一次连续交了几遍A的程序,我的状态莫名好看啊233
总结:
1.开始用define简化代码
2.写的时候出现了手抖,还不够熟练
3.剖分基本上没有问题,线段树题目欠多
1 #include <cstdio> 2 #include <iostream> 3 #define lson now*2 4 #define rson now*2+1 5 #define mid (l+r)/2 6 using namespace std; 7 int cnt=0,n,m; 8 int flag[400001],t[400001]; 9 int fa[100001],size[100001],son[100001],bro[100001],b[100001],pos[100001],top[100001]; 10 int dfs1(int k) 11 { 12 size[k]=1; 13 for(int i=son[k];i!=0;i=bro[i]) 14 size[k]+=dfs1(i); 15 return size[k]; 16 } 17 void dfs2(int k,int to) 18 { 19 b[++cnt]=k; 20 top[k]=to; 21 int max=son[k]; 22 pos[k]=cnt; 23 for(int i=son[k];i!=0;i=bro[i]) 24 if(size[i]>size[max]) 25 max=i; 26 if(max==0) 27 return; 28 dfs2(max,to); 29 for(int i=son[k];i!=0;i=bro[i]) 30 if(i!=max) 31 dfs2(i,i); 32 } 33 void down(int now,int l,int r) 34 { 35 if(flag[now]==1) 36 { 37 flag[lson]=1; 38 flag[rson]=1; 39 t[lson]=mid-l+1; 40 t[rson]=r-mid; 41 flag[now]=0; 42 } 43 if(flag[now]==2) 44 { 45 flag[lson]=2; 46 flag[rson]=2; 47 t[lson]=0; 48 t[rson]=0; 49 flag[now]=0; 50 } 51 } 52 int que(int now,int l,int r,int x,int y) 53 { 54 if(l==x && r==y) return t[now]; 55 down(now,l,r); 56 return ((x<=mid)?que(lson,l,mid,x,min(y,mid)):0)+((y>mid)?que(rson,mid+1,r,max(x,mid+1),y):0); 57 } 58 void set_0(int now,int l,int r,int x,int y) 59 { 60 if(l==x && r==y) 61 { 62 flag[now]=2; 63 t[now]=0; 64 return; 65 } 66 down(now,l,r); 67 if(x<=mid) 68 set_0(lson,l,mid,x,min(y,mid)); 69 if(y>mid) 70 set_0(rson,mid+1,r,max(x,mid+1),y); 71 t[now]=t[lson]+t[rson]; 72 } 73 void set_1(int now,int l,int r,int x,int y) 74 { 75 if(l==x && r==y) 76 { 77 flag[now]=1; 78 t[now]=r-l+1; 79 return; 80 } 81 down(now,l,r); 82 if(x<=mid) 83 set_1(lson,l,mid,x,min(y,mid)); 84 if(y>mid) 85 set_1(rson,mid+1,r,max(x,mid+1),y); 86 t[now]=t[lson]+t[rson]; 87 } 88 int main() 89 { 90 scanf("%d",&n); 91 for(int i=2;i<=n;i++) 92 { 93 scanf("%d",&fa[i]); 94 fa[i]++; 95 bro[i]=son[fa[i]]; 96 son[fa[i]]=i; 97 } 98 dfs1(1); 99 dfs2(1,1); 100 scanf("%d",&m); 101 for(int i=1;i<=m;i++) 102 { 103 char ch=getchar(); 104 while(ch!='i' && ch!='u') 105 ch=getchar(); 106 bool b=ch=='i'; 107 int x=0; 108 while(ch<'0' || ch>'9') 109 ch=getchar(); 110 while(ch>='0' && ch<='9') 111 { 112 x=x*10+ch-'0'; 113 ch=getchar(); 114 } 115 x++; 116 if(b) 117 { 118 int sum=0; 119 for(int i=top[x];1;i=top[x]) 120 { 121 sum+=pos[x]-pos[i]+1-que(1,1,n,pos[i],pos[x]); 122 set_1(1,1,n,pos[i],pos[x]); 123 if(i==1) 124 break; 125 x=fa[i]; 126 } 127 printf("%d\n",sum); 128 } 129 else 130 { 131 printf("%d\n",que(1,1,n,pos[x],pos[x]+size[x]-1)); 132 set_0(1,1,n,pos[x],pos[x]+size[x]-1); 133 } 134 } 135 return 0; 136 }