[集训]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 }
View Code

猜你喜欢

转载自www.cnblogs.com/GreenDuck/p/11136218.html