利用dfs序(先序遍历),将树对应到一维数组上。然后用线段树更新求解。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=50050;
vector<int> vec[MAXN];
int sonsum[MAXN],w[MAXN],mp[MAXN],num[MAXN];
int tim;
struct node
{
int l,r;
long long nsum,inc;
}segtree[MAXN*3];
void build(int i,int l,int r)
{
segtree[i].l=l;
segtree[i].r=r;
segtree[i].inc=0;
if(l==r)
{
segtree[i].nsum=num[l];
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
segtree[i].nsum=segtree[i<<1].nsum+segtree[i<<1|1].nsum;
}
void add(int i,int a,int b,long long c)
{
if(segtree[i].l==a&&segtree[i].r==b)
{
segtree[i].inc+=c;
return;
}
segtree[i].nsum+=c*(b-a+1);
int mid=(segtree[i].l+segtree[i].r)>>1;
if(b<=mid)
add(i<<1,a,b,c);
else if(a>mid)
add(i<<1|1,a,b,c);
else
{
add(i<<1,a,mid,c);
add(i<<1|1,mid+1,b,c);
}
}
long long query(int i,int a,int b)
{
if(segtree[i].l==a&&segtree[i].r==b)
{
return segtree[i].nsum+(b-a+1)*segtree[i].inc;
}
segtree[i].nsum+=(segtree[i].r-segtree[i].l+1)*segtree[i].inc;
int mid=(segtree[i].l+segtree[i].r)>>1;
add(i<<1,segtree[i].l,mid,segtree[i].inc);
add(i<<1|1,mid+1,segtree[i].r,segtree[i].inc);
segtree[i].inc=0;
if(b<=mid)
return query(i<<1,a,b);
else if(a>mid)
return query(i<<1|1,a,b);
else
return query(i<<1,a,mid)+query(i<<1|1,mid+1,b);
}
void dfs(int x)
{
mp[x]=tim++;
sonsum[x]=1;
for(int i=0;i<vec[x].size();i++)
{
dfs(vec[x][i]);
sonsum[x]+=sonsum[vec[x][i]];
}
}
int main()
{
long long n,m,i,p,x,y,z;
char op;
while(~scanf("%lld%lld",&n,&m))
{
for(i=1;i<n;i++)
vec[i].clear();
w[0]=0;
for(i=1;i<n;i++)
{
scanf("%lld%lld",&p,&w[i]);
vec[p].push_back(i);
}
tim=1;
dfs(0);
for(i=0;i<n;i++)
num[mp[i]]=w[i];
build(1,1,n);
while(m--)
{
scanf(" %c %lld%lld%lld",&op,&x,&y,&z);
if(op=='S')
{
if(query(1,mp[x],mp[x])<y)
add(1,mp[x],mp[x],z);
}
else
{
if(query(1,mp[x],mp[x]+sonsum[x]-1)<y*sonsum[x])
add(1,mp[x],mp[x]+sonsum[x]-1,z);
}
}
for(i=0;i<n;i++)
printf("%lld\n",query(1,mp[i],mp[i]));
}
}