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