This dynamic point division, gdkoi when listening to hit, there are classmates talked about, so the impression is more profound also think out, and then in the realization of the card for a long time =
I have to say that CLJ is really too simple, and the implementation is not mentioned at all.
First we can use the tree to divide and conquer the tree, that is, the center of gravity of the tree as the root node and then the sub-tree for the center of his subtree recursion, and then each node is the information of its subtree.
For each node, the sum of the DV that we have saved this subtree has been used as the answer value for the point
This allows the modification to be resolved within the time of log n
When looking for an answer, we can find that if the sub-tree of the node now is more than the total node, then it must be better than the original scheme in that direction.
We start with the root node, if we find the answer in a subtrees tree, we consider how to turn the answer of its son node into the answer of the whole tree, we can find that all the nodes except this subtree can be shrunk to a node and connected to the subtrees tree, and then can continue to do so, find the operation and then undo these
So I still have to maintain some weird stuff, but it's pretty short.
Code:
#include <cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<vector>using namespacestd;#defineMAXN 100100typedefLong LongLl;typedef pair<ll,ll>Ii;typedef pair<ll,ii>III;#defineFi first#defineSe Second#definePB Push_backstructedges{intTo,next,dist;} edge[maxn*2];intL,next[maxn];inlinevoidAddedge (intXintYintz) {edge[++l]= (edges) {y,next[x],z};next[x]=l; edge[++l]= (edges) {x,next[y],z};next[y]=l;}BOOLDONE[MAXN];ints[maxn],f[maxn],root,size;voidDfsintUintFA) {S[u]=1; f[u]=0; intv=0; for(intI=next[u];i;i=Edge[i].next) { if(done[v=edge[i].to]| | V==FA)Continue; DFS (V,U); S[u]+=S[v]; F[u]=Max (F[u],s[v]); } F[u]=max (f[u],size-S[u]); if(F[u]<f[root]) root=u;} Vector<ii>PRE[MAXN];voidGetdist (intUintFaintTarintDist) {PRE[U].PB (II (Tar,dist)); S[u]=1;intv=0; for(intI=next[u];i;i=Edge[i].next) { if(done[v=edge[i].to]| | V==FA)Continue; Getdist (V,u,tar,dist+edge[i].dist); S[u]+=S[v]; }}vector<iii>CH[MAXN];voidWorkintu) {Done[u]=1; intv=0; PRE[U].PB (II (U,0)); for(intI=next[u];i;i=Edge[i].next) { if(Done[v=edge[i].to])Continue; Getdist (V,0, u,edge[i].dist); f[0]=size=S[v]; DFS (V,root=0); CH[U].PB (iii (ROOT,II (v,edge[i].dist))); Work (root); }}ll Cnt[maxn],sum[maxn];vector<ll>Sumdist[maxn];inlinevoidUpdateintx,ll y,ll z) { for(intI=0; I<pre[x].size (); i++) { intu=pre[x][i].fi; Cnt[u]+=y;sum[u]+=z+y*pre[x][i].se; if(I!=pre[x].size ()-1) { intj=0; for(; J<ch[u].size (); j + +) if(ch[u][j].fi==pre[x][i+1].fi) sumdist[u][j]+=z+y*pre[x][i].se; } }}intRealroot;vector<iii>record;inline ll query () {intx=Realroot; intmx=0; Record.clear (); while(x) {MX=0; for(intI=1; I<ch[x].size (); i++) if(cnt[ch[x][mx].fi]<cnt[ch[x][i].fi]) mx=i; if(ch[x].size () = =0|| cnt[ch[x][mx].fi]*2<=Cnt[x]) {ll ans=Sum[x]; for(intI=0; I<record.size (); i++) update (record[i].fi,record[i].se.fi,record[i].se.se); returnans; } intv=ch[x][mx].fi; RECORD.PB (III (CH[X][MX].SE.FI,II (-(cnt[x]-Cnt[v]),-(sum[x]-sumdist[x][mx]+ (Cnt[x]-cnt[v]) *ch[x][mx].se.se))) ; Update (CH[X][MX].SE.FI,CNT[X)-Cnt[v], sum[x]-sumdist[x][mx]+ (Cnt[x]-cnt[v]) *ch[x][mx].se.se); X=v; }}intMain () {intn,q; scanf ("%d%d",&n,&Q); for(intI=1; i<n;i++) { intx, Y, Z scanf ("%d%d%d",&x,&y,&z); Addedge (x, y, z); } f[0]=size=N; DFS (1, root=0); Realroot=Root; Work (root); for(intI=1; i<=n;i++) sumdist[i]=vector<ll> (Ch[i].size (),0); while(q--) { intx, y; scanf ("%d%d",&x,&y); Update (x, Y,0); printf ("%lld\n", query ()); } return 0;}
Bzoj 3924: [Zjoi2015] Fantasy Township strategy game (Dynamic Point Division)