Topic: Given a tree, each point has a point right, several times to change the point of the right, multiple queries with the right center of gravity to all points of the sum of the right distance
No regrets in this life into the east, the afterlife is willing to birth fantasy Township
First we consider how to calculate the sum of the weighted distances of a point to all points and support the modification
It would be nice to divide it with a dynamic tree.
Each point records the sum of the weighted distance in the subtree, and the sum of the weights, and then records a version that needs to be lost in each subtree.
and sweep up to the root to count.
↑ This paragraph of the face will write dynamic tree division of the people, will not be first to cut hide and seek
And then it's done.
For each point of the split structure, we enumerate its out edges
If the sum of the distance from the point to which the edge is connected is less than the current point, then the answer must be in the sub-tree where the edge is pointing, and the Division will be done.
If there is no edge less than the current point, then the current point is the center of gravity
Note the difference between "point pointing out" and "split child node" = =
Time complexity O (nlog^2n*20)
Two-point distance to be used Rmqlca or complexity of multiple log BZ on the cross
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 100100using namespace Std;int n,m;namespace tree{struct abcd{int to,f,next;bool ban;} Table[m<<1];int Head[m],tot=1;int Fa[m],dpt[m],dis[m];int log_2[m<<1],pos[m],a[m<<1][20];void ADD (int x,int y,int z) {Table[++tot].to=y;table[tot].f=z;table[tot].next=head[x];head[x]=tot;} void DFS (int x) {static int t=0;int i;dpt[x]=dpt[fa[x]]+1;a[pos[x]=++t][0]=dis[x];for (i=head[x];i;i=table[i].next) if (Table[i].to!=fa[x]) {Fa[table[i].to]=x;dis[table[i].to]=dis[x]+table[i].f;dfs (table[i].to); a[++t][0]=dis[x];}} void Build_lca () {int i,j;for (i=2;i<=n-1<<1;i++) log_2[i]=log_2[i>>1]+1;for (j=1;j<=log_2[n-1< <1];j++) for (i=1;i+ (1<<j) -1<=n-1<<1;i++) a[i][j]=min (a[i][j-1],a[i+ (1<<j-1)][j-1]);} int lca_distance (int x,int y) {x=pos[x];y=pos[y];if (x>y) swap (x, y), int l=log_2[y-x+1];return min (a[x][l],a[y-(1 <<l) +1][l]);} int Distance (int x,int y) {REturn dis[x]+dis[y]-2*lca_distance (x, y);}} namespace Dynamic_tdc{struct abcd{int To,first,next;} _table[m];int _head[m],_tot;int Root,fa[m];long long dis_sum1[m],dis_sum2[m],sum1[m],sum2[m];void Add (int x,int y,int z) {_table[++_tot].to=y;_table[_tot].first=z;_table[_tot].next=_head[x];_head[x]=_tot;} int get_size (int x,int from) {int i,size=1;for (i=tree::head[x];i;i=tree::table[i].next) {if (Tree::table[i].ban) Continue;if (Tree::table[i].to==from) continue;size+=get_size (tree::table[i].to,x);} return size;} int get_centre_of_gravity (int x,int from,int size,int &cg) {int i,re=1,flag=1;for (i=tree::head[x];i;i=tree::table [I].next) {if (Tree::table[i].ban) continue;if (tree::table[i].to==from) Continue;int temp=get_centre_of_gravity ( TREE::TABLE[I].TO,X,SIZE,CG); if (temp<<1>size) flag=0;re+=temp;} if (size-re<<1>size) flag=0;if (flag) Cg=x;return re;} int tree_divide_and_conquer (int x) {int i,size=get_size (x,0); Get_centre_of_gravity (x,0,size,x); for (I=tree::head[x];i;i=tree::table[i].next) {if (TRee::table[i].ban) continue; Tree::table[i].ban=true; Tree::table[i^1].ban=true;int Temp=tree_divide_and_conquer (tree::table[i].to); fa[temp]=x; ADD (x,temp,tree::table[i].to);} return x;} void Modify (int x,int delta) {int i;sum1[x]+=delta;for (i=x;fa[i];i=fa[i]) {int dis=tree::D istance (X,fa[i]);d is_sum1[ fa[i]]+= (Long Long) dis*delta;dis_sum2[i]+= (long Long) Dis*delta;sum1[fa[i]]+=delta;sum2[i]+=delta;}} Long long Calculate (int x) {int i;long long re=dis_sum1[x];for (I=x;fa[i];i=fa[i]) {int dis=tree::D istance (X,fa[i]); re+= dis_sum1[fa[i]]-dis_sum2[i];re+= (Sum1[fa[i]]-sum2[i]) *dis;} return re;} Long long Query (int x) {int I;long long cost=calculate (x); for (I=_head[x];i;i=_table[i].next) {Long Long temp=calculate (_ Table[i].first); if (temp<cost) return Query (_table[i].to);} return cost;}} Namespace istream{#define L (1<<16) char Get_char () {static char buffer[l],*s,*t;if (s==t) {t= (S=buffer) +fread ( Buffer,1,l,stdin); if (s==t) return EOF;} return *s++;} int Get_int () {bool Flag=false;char c;int re=0;do C=get_char (); while (c< ' 0 ' | | C> ' 9 ') &&c!= '-'), if (c== '-') Flag=true,c=get_char (); while (c>= ' 0 ' &&c<= ' 9 ') re= (re<<1 ) + (RE<<3) + (c ' 0 '), C=get_char (); return flag?-re:re;}} struct Ostream{char buffer[l],*s;ostream () {s=buffer;} void Put_char (Char c) {*s++=c;if (s==buffer+l) fwrite (buffer,1,l,stdout), S=buffer;} void Put_long_long (Long long x) {static int stack[20],top;if (!x) stack[++top]= ' 0 '; while (x) stack[++top]=x%10+ ' 0 ', x/=10 while (top) Put_char (stack[top--]); Put_char (' \ n ');} ~ostream () {fwrite (buffer,1,s-buffer,stdout);}} Os;int Main () {using namespace Istream;int i,x,y,z;cin>>n>>m;for (i=1;i<n;i++) {x=get_int (); Y=get_int ( ); Z=get_int (); Tree::add (x, y, z); Tree::add (y,x,z);} Tree::D FS (1); Tree::build_lca ();D ynamic_tdc::root=dynamic_tdc::tree_divide_and_conquer (1); for (i=1;i<=m;i++) {x=Get_Int (); y =get_int ();D ynamic_tdc::modify (x, y), Long long temp=dynamic_tdc::query (dynamic_tdc::root); Os.put_long_long (temp);} return 0;}
Bzoj 3924 Zjoi2015 Fantasy Township Strategy game dynamic Tree partition