洛谷P3676 小清新数据结构题(动态点分治)

题面在这里>>>

解题思路:

开始写了个LCT后来发现是错的QAQ

正解是动态点分治。

剩下的部分和幻想乡那道题就一样了。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll spc<<1
  5 #define rrr spc<<1|1
  6 typedef long long lnt;
  7 const int N=200010;
  8 struct trnt{
  9     lnt sum;
 10     lnt lzt;
 11 }tr[N<<2];
 12 struct pnt{
 13     int hd;
 14     int fa;
 15     int dp;
 16     int tp;
 17     int ft;
 18     int ind;
 19     int oud;
 20     int wgt;
 21     int mxs;
 22     lnt val;
 23     lnt sum;
 24     lnt Sum;
 25     int eind;
 26     lnt diss;
 27     lnt disf;
 28     bool vis;
 29 }p[N];
 30 struct ent{
 31     int twd;
 32     int lst;
 33 }e[N<<1];
 34 int rt;
 35 int n,m;
 36 int cnt;
 37 int dfn;
 38 int tdn;
 39 int root;
 40 int size;
 41 int maxsize;
 42 int lg[N<<2];
 43 int eula[N<<2][21];
 44 lnt w;
 45 lnt V;
 46 lnt val[N];
 47 void pushup(int spc)
 48 {
 49     tr[spc].sum=tr[lll].sum+tr[rrr].sum;
 50     return ;
 51 }
 52 void add(int spc,int l,int r,lnt v)
 53 {
 54     tr[spc].lzt+=v;
 55     tr[spc].sum+=v*(r-l+1);
 56     return ;
 57 }
 58 void pushdown(int l,int mid,int r,int spc)
 59 {
 60     if(tr[spc].lzt)
 61     {
 62         lnt v=tr[spc].lzt;
 63         add(lll,l,mid,v);
 64         add(rrr,mid+1,r,v);
 65         tr[spc].lzt=0;
 66     }
 67     return ;
 68 }
 69 void build(int l,int r,int spc)
 70 {
 71     if(l==r)
 72     {
 73         tr[spc].sum=val[l];
 74         return ;
 75     }
 76     int mid=(l+r)>>1;
 77     build(l,mid,lll);
 78     build(mid+1,r,rrr);
 79     pushup(spc);
 80     return ;
 81 }
 82 void update(int l,int r,int ll,int rr,int spc,lnt v)
 83 {
 84     if(ll>r||l>rr)
 85         return ;
 86     if(ll<=l&&r<=rr)
 87     {
 88         add(spc,l,r,v);
 89         return ;
 90     }
 91     int mid=(l+r)>>1;
 92     pushdown(l,mid,r,spc);
 93     update(l,mid,ll,rr,lll,v);
 94     update(mid+1,r,ll,rr,rrr,v);
 95     pushup(spc);
 96     return ;
 97 }
 98 lnt query(int l,int r,int ll,int rr,int spc)
 99 {
100     if(ll>r||l>rr)
101         return 0;
102     if(ll<=l&&r<=rr)
103         return tr[spc].sum;
104     int mid=(l+r)>>1;
105     pushdown(l,mid,r,spc);
106     return query(l,mid,ll,rr,lll)+query(mid+1,r,ll,rr,rrr);
107 }
108 void ade(int f,int t)
109 {
110     cnt++;
111     e[cnt].twd=t;
112     e[cnt].lst=p[f].hd;
113     p[f].hd=cnt;
114     return ;
115 }
116 void E_dfs(int x,int f)
117 {
118     eula[++dfn][0]=x;
119     p[x].eind=dfn;
120     p[x].dp=p[f].dp+1;
121     p[x].ft=f;
122     p[x].wgt=1;
123     int maxs=-1;
124     for(int i=p[x].hd;i;i=e[i].lst)
125     {
126         int to=e[i].twd;
127         if(to==f)
128             continue;
129         E_dfs(to,x);
130         p[x].wgt+=p[to].wgt;
131         eula[++dfn][0]=x;
132         if(maxs<p[to].wgt)
133         {
134             maxs=p[to].wgt;
135             p[x].mxs=to;
136         }
137     }
138     return ;
139 }
140 void Build_dfs(int x,int top)
141 {
142     if(!x)
143         return ;
144     p[x].ind=++tdn;
145     p[x].tp=top;
146     Build_dfs(p[x].mxs,top);
147     for(int i=p[x].hd;i;i=e[i].lst)
148     {
149         int to=e[i].twd;
150         if(p[to].ind)
151             continue;
152         Build_dfs(to,to);
153     }
154     p[x].oud=tdn;
155     return ;
156 }
157 void Add_dfs(int x,int f)
158 {
159     p[x].Sum=p[x].val;
160     for(int i=p[x].hd;i;i=e[i].lst)
161     {
162         int to=e[i].twd;
163         if(to==f)
164             continue;
165         Add_dfs(to,x);
166         p[x].Sum+=p[to].Sum;
167     }
168     val[p[x].ind]=p[x].Sum;
169     V+=p[x].Sum*(w-p[x].Sum);
170     return ;
171 }
172 int Emin(int x,int y)
173 {
174     return p[x].dp<p[y].dp?x:y;
175 }
176 int Lca(int x,int y)
177 {
178     x=p[x].eind;
179     y=p[y].eind;
180     if(x>y)
181         std::swap(x,y);
182     int l=lg[y-x+1];
183     return Emin(eula[x][l],eula[y-(1<<l)+1][l]);
184 }
185 int Dis(int x,int y)
186 {
187     int z=Lca(x,y);
188     return p[x].dp+p[y].dp-2*p[z].dp;
189 }
190 void grc_dfs(int x,int f)
191 {
192     p[x].wgt=1;
193     int maxs=-1;
194     for(int i=p[x].hd;i;i=e[i].lst)
195     {
196         int to=e[i].twd;
197         if(to==f||p[to].vis)
198             continue;
199         grc_dfs(to,x);
200         p[x].wgt+=p[to].wgt;
201         if(maxs<p[to].wgt)
202             maxs=p[to].wgt;
203     }
204     maxs=std::max(maxs,size-p[x].wgt);
205     if(maxs<maxsize)
206     {
207         maxsize=maxs;
208         root=x;
209     }
210     return ;
211 }
212 void bin_dfs(int x,int f)
213 {
214     p[x].fa=f;
215     p[x].vis=true;
216     int tmp=size;
217     for(int i=p[x].hd;i;i=e[i].lst)
218     {
219         int to=e[i].twd;
220         if(p[to].vis)
221             continue;
222         root=0;
223         if(p[x].wgt<p[to].wgt)
224             size=tmp-p[x].wgt;
225         else
226             size=p[to].wgt;
227         maxsize=0x3f3f3f3f;
228         grc_dfs(to,to);
229         bin_dfs(root,x);
230     }
231     return ;
232 }
233 void update(int x,lnt y)
234 {
235     p[x].sum+=y;
236     for(int i=x;p[i].fa;i=p[i].fa)
237     {
238         lnt tmp=Dis(x,p[i].fa)*y;
239         p[i].disf+=tmp;
240         p[p[i].fa].diss+=tmp;
241         p[p[i].fa].sum+=y;
242     }
243     return ;
244 }
245 lnt Query(int x)
246 {
247     lnt ans=p[x].diss;
248     for(int i=x;p[i].fa;i=p[i].fa)
249     {
250         lnt tmp=Dis(x,p[i].fa);
251         ans+=p[p[i].fa].diss-p[i].disf;
252         ans+=tmp*(p[p[i].fa].sum-p[i].sum);
253     }
254     return ans;
255 }
256 void Update(int x,lnt v)
257 {
258     while(p[x].tp!=p[1].tp)
259     {
260         update(1,tdn,p[p[x].tp].ind,p[x].ind,1,v);
261         x=p[p[x].tp].ft;
262     }
263     update(1,tdn,p[1].ind,p[x].ind,1,v);
264     return ;
265 }
266 int main()
267 {
268     scanf("%d%d",&n,&m);
269     for(int i=1;i<n;i++)
270     {
271         int a,b;
272         scanf("%d%d",&a,&b);
273         ade(a,b);
274         ade(b,a);
275     }
276     E_dfs(1,1);
277     Build_dfs(1,1);
278     for(int i=2;i<=dfn;i++)
279         lg[i]=lg[i>>1]+1;
280     for(int i=1;i<=20;i++)
281         for(int j=1;j+(1<<i)-1<=dfn;j++)
282             eula[j][i]=Emin(eula[j][i-1],eula[j+(1<<(i-1))][i-1]);
283     root=0;
284     size=n;
285     maxsize=0x3f3f3f3f;
286     grc_dfs(1,1);
287     rt=root;
288     bin_dfs(root,0);
289     for(int i=1;i<=n;i++)
290     {
291         scanf("%lld",&p[i].val);
292         update(i,p[i].val);
293         w+=p[i].val;
294     }
295     Add_dfs(1,1);
296     while(m--)
297     {
298         int cmd;
299         scanf("%d",&cmd);
300         if(cmd==1)
301         {
302             int x,y;
303             scanf("%d%d",&x,&y);
304             lnt dv=y-p[x].val;
305             update(x,dv);
306             V+=dv*Query(x);
307             w+=dv;
308             p[x].val=y;
309         }else{
310             int x;
311             scanf("%d",&x);
312             lnt ans=-V+w*w;
313             ans+=Query(x)*w;
314             printf("%lld\n",ans);
315         }
316     }
317     return 0;
318 }

猜你喜欢

转载自www.cnblogs.com/blog-Dr-J/p/10160494.html
今日推荐