对一颗n个节点的树操作。
有两种操作,第一种是对子树j,j的点权+k,j的儿子们点权+k+1,j的孙子们点权+k+2,以此类推。
第二种操作询问子树点权和。
修改操作实际上是对子树每个点i加上k-d[j]+d[i]
标记可以写成(a,b)表示一个点权为x的点i经过后变成x+a+d[i]*b
显然这个标记可合并而且容易求和。
线段树维护即可。
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=50000+10;
ll tree[maxn*4],sum[maxn*4],a[maxn*4],b[maxn*4];
int h[maxn],go[maxn],nxt[maxn],d[maxn],dfn[maxn],nfd[maxn],size[maxn];
int i,j,k,l,t,n,m,tot,top;
char ch;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void add(int x,int y){
go[++tot]=y;
nxt[tot]=h[x];
h[x]=tot;
}
void dfs(int x){
dfn[x]=++top;
nfd[top]=x;
int t=h[x];
size[x]=1;
while (t){
d[go[t]]=d[x]+1;
dfs(go[t]);
size[x]+=size[go[t]];
t=nxt[t];
}
}
void build(int p,int l,int r){
a[p]=b[p]=0;
if (l==r){
sum[p]=d[nfd[l]];
tree[p]=0;
return;
}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
sum[p]=sum[p*2]+sum[p*2+1];
}
char get(){
char ch=getchar();
while (ch!='A'&&ch!='Q') ch=getchar();
return ch;
}
void mark(int p,int l,int r,ll c,ll d){
tree[p]+=(ll)c*(r-l+1)+d*sum[p];
a[p]+=c;
b[p]+=d;
}
void down(int p,int l,int r){
int mid=(l+r)/2;
if (a[p]||b[p]){
mark(p*2,l,mid,a[p],b[p]);
mark(p*2+1,mid+1,r,a[p],b[p]);
a[p]=b[p]=0;
}
}
void change(int p,int l,int r,int a,int b,ll c,ll d){
if (l==a&&r==b){
mark(p,l,r,c,d);
return;
}
down(p,l,r);
int mid=(l+r)/2;
if (b<=mid) change(p*2,l,mid,a,b,c,d);
else if (a>mid) change(p*2+1,mid+1,r,a,b,c,d);
else{
change(p*2,l,mid,a,mid,c,d);
change(p*2+1,mid+1,r,mid+1,b,c,d);
}
tree[p]=tree[p*2]+tree[p*2+1];
}
ll query(int p,int l,int r,int a,int b){
if (l==a&&r==b) return tree[p];
down(p,l,r);
int mid=(l+r)/2;
if (b<=mid) return query(p*2,l,mid,a,b);
else if (a>mid) return query(p*2+1,mid+1,r,a,b);
else return query(p*2,l,mid,a,mid)+query(p*2+1,mid+1,r,mid+1,b);
}
int main(){
freopen("truetears.in","r",stdin);freopen("truetears.out","w",stdout);
n=read();m=read();
fo(i,2,n){
j=read();
add(j,i);
}
d[1]=1;
dfs(1);
build(1,1,n);
while (m--){
ch=get();
if (ch=='A'){
j=read();k=read();
change(1,1,n,dfn[j],dfn[j]+size[j]-1,k-d[j],1);
}
else{
j=read();
printf("%lld\n",query(1,1,n,dfn[j],dfn[j]+size[j]-1));
}
}
}