令1爲樹根,T=Σd[i],sum[x]是子樹x中的d之和,dis[x]是節點x的帶權深度。c++
對於節點x的兒子y,邊長爲w,若是y比x更優,則(T-sum[y])*w-sum[y]*w<=0即sum[y]>=T/2。ui
換句話說,若存在sum[y]>T/2,顯然y更優,且y只存在一個(對於x);若存在sum[y]=T/2,(1個或2個),由於y的子樹內都不存在sum>T/2的點,因此y就是一個最優解,沒必要遞歸地作。spa
考慮一類暴力求出最優勢:從根出發依次進入sum>T/2的兒子,最深的那個點即爲帶權重心。這能夠樹剖維護sum/區間最大值,若是右半區間(較深)存在>=T/2,即向右跳轉。code
設已經求出了最優勢R,答案是Σ(d[i]*dis[i]+d[i]*dis[R]-2*d[i]*dis[lca(R,i)]),套路地維護就好了。遞歸
意外的簡單?it
#include <bits/stdc++.h> #define ll long long #define trvl(x,i,y) for(int i=ehd[x],y; y=to[i],i; i=lst[i]) #define ls (x<<1) #define rs (x<<1|1) using namespace std; const int N=1e5+10; int n,m; int ehd[N],to[N<<1],len[N<<1],lst[N<<1]; int fa[N],siz[N],son[N],top[N],id[N],dfn[N]; ll S,T,dis[N]; void insert(int x,int y,int w) { static int cnt=0; to[++cnt]=y,len[cnt]=w,lst[cnt]=ehd[x],ehd[x]=cnt; to[++cnt]=x,len[cnt]=w,lst[cnt]=ehd[y],ehd[y]=cnt; } void dfs1(int x,int p) { fa[x]=p; siz[x]=1; trvl(x,i,y) if(y!=p) { dis[y]=dis[x]+len[i]; dfs1(y,x);siz[x]+=siz[y]; if(siz[y]>siz[son[x]]) son[x]=y; } } void dfs2(int x,int t) { static int cnt=0; top[dfn[id[x]=++cnt]=x]=t; if(son[x]) dfs2(son[x],t); trvl(x,i,y) if(son[x]!=y&&fa[x]!=y) dfs2(y,y); } int tag[N<<2],mx[N<<2]; ll c[N<<2],s[N<<2]; void psd(int x) { if(!tag[x]) return; c[ls]+=s[ls]*tag[x],mx[ls]+=tag[x],tag[ls]+=tag[x]; c[rs]+=s[rs]*tag[x],mx[rs]+=tag[x],tag[rs]+=tag[x]; tag[x]=0; } void upd(int x) { mx[x]=max(mx[ls],mx[rs]); c[x]=c[ls]+c[rs]; } void build(int x,int l,int r) { if(l==r) { s[x]=dis[dfn[l]]-dis[fa[dfn[l]]]; return; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); s[x]=s[ls]+s[rs]; } int find(int x,int l,int r) { if(l==r) return dfn[l]; int mid=(l+r)>>1; psd(x); if(mx[rs]*2>T) return find(rs,mid+1,r); return find(ls,l,mid); } void mdf(int x,int l,int r,int L,int R,ll w) { if(L<=l&&r<=R) { c[x]+=s[x]*w,mx[x]+=w,tag[x]+=w; return; } int mid=(l+r)>>1; psd(x); if(L<=mid) mdf(ls,l,mid,L,R,w); if(mid<R) mdf(rs,mid+1,r,L,R,w); upd(x); } ll qry(int x,int l,int r,int L,int R) { if(L<=l&&r<=R) return c[x]; int mid=(l+r)>>1; ll c=0; psd(x); if(L<=mid) c+=qry(ls,l,mid,L,R); if(mid<R) c+=qry(rs,mid+1,r,L,R); return c; } void modify(int x,int w) { for(; x; x=fa[top[x]]) mdf(1,1,n,id[top[x]],id[x],w); } ll query(int x,ll w=0) { for(; x; x=fa[top[x]]) w+=qry(1,1,n,id[top[x]],id[x]); return w; } int main() { scanf("%d%d",&n,&m); for(int x,y,w,i=n; --i; ) { scanf("%d%d%d",&x,&y,&w); insert(x,y,w); } dfs1(1,0); dfs2(1,1); build(1,1,n); for(int x,w; m--; ) { scanf("%d%d",&x,&w); modify(x,w); S+=dis[x]*w; T+=w; x=find(1,1,n); printf("%lld\n",S+T*dis[x]-2*query(x)); } return 0; }