题意
一颗有根树,每个点有黑白两种颜色和阀值ai,若它的子树中(不包括自己)的黑色数量大于ai,则产生一点贡献。每次将一个点的颜色取反,求每次修改后的贡献。n,q<=1E5。
思考
树剖后直接分块就行了。复杂度约为O((n+q)sqrt(nlogn)),但似乎更小?
代码
1 #pragma GCC optimize 2 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int maxn=1E5+5; 5 /////////////////////////////////////////////////////////////////////////////// 6 int wait[maxn],wait_R[maxn],wait_C[maxn],wait_W[maxn]; 7 template<class T>inline void copy(T*A,T*B,int l,int r) 8 { 9 for(int i=l;i<=r;++i) 10 A[i-l+1]=B[i]; 11 } 12 struct block 13 { 14 int n,pos,layer,now; 15 bool created; 16 int*f,*c; 17 block() 18 { 19 created=now=0; 20 } 21 void init(int x,int where,int*A) 22 { 23 if(created) 24 delete f,delete c; 25 created=1; 26 for(int i=1;i<=x;++i) 27 wait_R[i]=A[i],wait_C[i]=0; 28 sort(wait_R+1,wait_R+x+1); 29 int size=0; 30 for(int i=1;i<=x;++i) 31 { 32 if(wait_R[i]!=wait_R[i-1]||i==1) 33 wait_W[++size]=wait_R[i]; 34 ++wait_C[size]; 35 } 36 n=size; 37 f=new int[n+2]; 38 c=new int[n+2]; 39 now=c[0]=f[0]=c[n+1]=f[n+1]=0; 40 layer=where; 41 pos=1; 42 for(int i=1;i<=n;++i) 43 f[i]=wait_W[i],c[i]=wait_C[i]; 44 while(f[pos]<layer) 45 now+=c[pos],++pos; 46 } 47 inline int get() 48 { 49 return now; 50 } 51 inline void add() 52 { 53 if(layer+1==f[pos]+1) 54 now+=c[pos],++pos; 55 ++layer; 56 } 57 inline void remove() 58 { 59 if(pos&&layer-1==f[pos-1]) 60 now-=c[pos-1],--pos; 61 --layer; 62 } 63 }; 64 struct sequence 65 { 66 int*a,*tag,*bel,*tail; 67 block*B; 68 int n,sqr,tot; 69 void init(int x,int*A) 70 { 71 n=x; 72 sqr=sqrt(n+0.5); 73 a=new int[n+3]; 74 bel=new int[n+3]; 75 tag=new int[sqr+3]; 76 tail=new int[sqr+3]; 77 for(int i=0;i<=sqr+1;++i) 78 tail[i]=tag[i]=0; 79 a[0]=0; 80 for(int i=1;i<=n;++i) 81 a[i]=A[i]; 82 int L=1,R=sqr; 83 B=new block[sqr+3]; 84 tot=0; 85 while(L<=n) 86 { 87 int len=min(n,R)-L+1; 88 copy(wait,a,L,min(n,R)); 89 B[++tot].init(len,0,wait); 90 for(int i=L;i<=R;++i) 91 bel[i]=tot; 92 tail[tot]=min(n,R); 93 L+=sqr,R+=sqr; 94 } 95 } 96 inline int get() 97 { 98 int sum=0; 99 for(int i=1;i<=tot;++i) 100 sum+=B[i].now; 101 return sum; 102 } 103 inline void add(int x) 104 { 105 int i=1; 106 for(i=1;bel[i]!=bel[x];i+=sqr) 107 B[bel[i]].add(); 108 int L=i,R=tail[bel[x]]; 109 int len=R-L+1; 110 for(int i=L;i<=R;++i) 111 wait[i-L+1]=a[i]-B[bel[x]].layer; 112 for(int i=L;i<=x;++i) 113 --wait[i-L+1]; 114 for(int i=L;i<=R;++i) 115 a[i]=wait[i-L+1]; 116 B[bel[x]].init(len,0,wait); 117 } 118 inline void remove(int x) 119 { 120 int i=1; 121 for(i=1;bel[i]!=bel[x];i+=sqr) 122 B[bel[i]].remove(); 123 int L=i,R=tail[bel[x]]; 124 int len=R-L+1; 125 for(int i=L;i<=R;++i) 126 wait[i-L+1]=a[i]-B[bel[x]].layer; 127 for(int i=L;i<=x;++i) 128 ++wait[i-L+1]; 129 for(int i=L;i<=R;++i) 130 a[i]=wait[i-L+1]; 131 B[bel[x]].init(len,0,wait); 132 } 133 inline void addDot(int x,int y) 134 { 135 int i=1; 136 while(bel[i]!=bel[x]) 137 i+=sqr; 138 int L=i,R=tail[bel[x]]; 139 int len=R-L+1; 140 for(int i=L;i<=R;++i) 141 wait[i-L+1]=a[i]-B[bel[x]].layer; 142 wait[x-L+1]+=y; 143 for(int i=L;i<=R;++i) 144 a[i]=wait[i-L+1]; 145 B[bel[x]].init(len,0,wait); 146 } 147 }S[maxn]; 148 /////////////////////////////////////////////////////////////////////////////// 149 int n,q,a[maxn]; 150 int size,head[maxn*2]; 151 int sum[maxn],fa[maxn],son[maxn],top[maxn],where[maxn],dfn[maxn],low[maxn],ti; 152 int tot,ans; 153 bool c[maxn]; 154 struct edge 155 { 156 int to,next; 157 }E[maxn*2]; 158 void dfs1(int u,int F) 159 { 160 fa[u]=F,sum[u]=1; 161 for(int i=head[u];i;i=E[i].next) 162 { 163 int v=E[i].to; 164 if(v==F) 165 continue; 166 dfs1(v,u); 167 sum[u]+=sum[v]; 168 if(sum[son[u]]<sum[v]) 169 son[u]=v; 170 } 171 } 172 void dfs2(int u,int F) 173 { 174 low[u]=dfn[u]=++ti; 175 if(son[F]==u) 176 top[u]=top[F]; 177 else 178 top[u]=u; 179 if(son[u]) 180 { 181 dfs2(son[u],u); 182 low[u]=low[son[u]]; 183 } 184 for(int i=head[u];i;i=E[i].next) 185 { 186 int v=E[i].to; 187 if(v==F||v==son[u]) 188 continue; 189 dfs2(v,u); 190 low[u]=low[v]; 191 } 192 } 193 void get(int u) 194 { 195 wait[where[u]=++tot]=a[u]; 196 if(son[u]) 197 get(son[u]); 198 } 199 void add(int u,int v) 200 { 201 E[++size].to=v; 202 E[size].next=head[u]; 203 head[u]=size; 204 } 205 void addChain(int x) 206 { 207 while(x) 208 { 209 S[top[x]].add(where[x]); 210 x=fa[top[x]]; 211 } 212 } 213 void removeChain(int x) 214 { 215 while(x) 216 { 217 S[top[x]].remove(where[x]); 218 x=fa[top[x]]; 219 } 220 } 221 int askChain(int x) 222 { 223 int sum=0; 224 while(x) 225 { 226 sum+=S[top[x]].get(); 227 x=fa[top[x]]; 228 } 229 return sum; 230 } 231 /////////////////////////////////////////////////////////////////////////////// 232 int main() 233 { 234 ios::sync_with_stdio(false); 235 int num; 236 cin>>num; 237 cin>>n>>q; 238 for(int i=2;i<=n;++i) 239 { 240 int x; 241 cin>>x; 242 add(x,i); 243 add(i,x); 244 } 245 for(int i=1;i<=n;++i) 246 cin>>a[i]; 247 dfs1(1,1); 248 dfs2(1,1); 249 fa[1]=0; 250 for(int u=1;u<=n;++u) 251 if(top[u]==u) 252 { 253 tot=0; 254 get(u); 255 S[u].init(tot,wait); 256 } 257 while(q--) 258 { 259 int x; 260 cin>>x; 261 if(c[x]) 262 { 263 int last=askChain(x); 264 removeChain(fa[x]); 265 S[top[x]].addDot(where[x],-666666); 266 int now=askChain(x); 267 ans+=now-last; 268 } 269 else 270 { 271 int last=askChain(x); 272 addChain(fa[x]); 273 S[top[x]].addDot(where[x],666666); 274 int now=askChain(x); 275 ans+=now-last; 276 } 277 c[x]^=1; 278 cout<<ans<<" "; 279 } 280 return 0; 281 }