将过程倒序,即每次放$\sum w_{son}$个石子并收回$w_{i}$个石子,并要求父亲优先于儿子操作
关于这个问题,其中一个弱化版(仅询问根节点)即hdu6326,具体做法可参考该链接
在此基础上,对每一个节点维护(仅考虑其子树内时)当前该点上的"怪兽"属性
此时,将$k$合并即将 $fa_{k}$到$fa_{k}$所在块最浅的点的链 上所有点的"怪兽"与$k$上的合并
将其差分,注意到所有$k$相对顺序不变(与合并顺序相同),进而线段树合并维护即可
时间复杂度为$o(n\log n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define M 10000000 5 #define ll long long 6 #define mid (l+r>>1) 7 int n,V,a[N],fa[N],rt[N],ls[M],rs[M],vis[M]; 8 vector<int>e[N],v[N]; 9 struct Data{ 10 ll a,b; 11 bool operator < (const Data &n)const{ 12 if ((a<b)!=(n.a<n.b))return a<b; 13 return (a<b ? a<n.a : b>n.b); 14 } 15 Data operator + (const Data &n)const{ 16 ll a0=max(a,a-b+n.a); 17 return Data{a0,b-a+n.b-n.a+a0}; 18 } 19 }w[N],W[N],ans[N],f[M];set<pair<Data,int> >S; 20 int find(int k){ 21 return (k==fa[k] ? k : fa[k]=find(fa[k])); 22 } 23 void update(int &k,int l,int r,int x){ 24 if (!k)k=++V; 25 if (l==r){ 26 vis[k]^=1,f[k]=(vis[k] ? W[l] : Data{0,0}); 27 return; 28 } 29 if (x<=mid)update(ls[k],l,mid,x); 30 else update(rs[k],mid+1,r,x); 31 f[k]=f[ls[k]]+f[rs[k]]; 32 } 33 int merge(int k1,int k2,int l,int r){ 34 if ((!k1)||(!k2))return k1+k2; 35 if (l==r){ 36 vis[k1]^=vis[k2],f[k1]=(vis[k1] ? W[l] : Data{0,0}); 37 return k1; 38 } 39 ls[k1]=merge(ls[k1],ls[k2],l,mid); 40 rs[k1]=merge(rs[k1],rs[k2],mid+1,r); 41 f[k1]=f[ls[k1]]+f[rs[k1]]; 42 return k1; 43 } 44 void dfs(int k){ 45 for(int i:e[k])dfs(i),rt[k]=merge(rt[k],rt[i],1,n-1); 46 for(int i:v[k])update(rt[k],1,n-1,i); 47 ans[k]=ans[k]+f[rt[k]]; 48 } 49 int main(){ 50 scanf("%*d%d",&n); 51 for(int i=2;i<=n;i++){ 52 scanf("%d",&a[i]); 53 e[a[i]].push_back(i); 54 } 55 for(int i=1;i<=n;i++){ 56 scanf("%lld",&w[i].b); 57 if (i>1)w[a[i]].a+=w[i].b; 58 } 59 for(int i=1;i<=n;i++){ 60 fa[i]=i,ans[i]=Data{w[i].b,0}+w[i]; 61 if (i>1)S.insert(make_pair(w[i],i)); 62 } 63 for(int i=1;i<n;i++){ 64 int k=(*S.begin()).second;S.erase(S.begin()); 65 int f=fa[k]=find(a[k]); 66 if (f>1)S.erase(make_pair(w[f],f)); 67 w[f]=w[f]+w[k],W[i]=w[k]; 68 v[a[k]].push_back(i),v[a[f]].push_back(i); 69 if (f>1)S.insert(make_pair(w[f],f)); 70 } 71 dfs(1); 72 for(int i=1;i<=n;i++)printf("%lld ",ans[i].a); 73 return 0; 74 }