题意

一颗有根树,每个点有黑白两种颜色和阀值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 }
View Code

 

 posted on 2019-07-05 08:55  GreenDuck  阅读(221)  评论(0编辑  收藏  举报