给一棵有根树,这棵树由编号为1~n的n个结点组成。根结点的编号为R。每个结点都有一个权值,结点i的权值为vi。 接下来有M组操作,操作分为两类: 1 a x,表示将结点a的子树上所有结点的权值增加x; 2 a,表示求结点a的子树上所有结点的权值之和。
第一行有三个整数n, m和R。 第二行有n个整数,第i个整数表示vi。 在接下来的n-1行中,每行两个整数,表示一条边。 在接下来的m行中,每行一组操作。
对于每组2 a操作,输出一个整数,表示[以结点a为根的子树]上所有结点的权值之和。
#include<bits/stdc++.h>
using namespace std;
int n,m,root,v[1000005],tot,head[1000005],Next[2000005],vet[2000005],tst,in[1000005],out[1000005];
long long c[1000005];
void add(int a,int b)
{
Next[++tot]=head[a];
vet[tot]=b;
head[a]=tot;
return;
}
int lowbit(int x)
{
return x&-x;
}
void pushup(int x,int y,int f)
{
for(int i=head[x];i;i=Next[i])
{
int j=vet[i];
if(j==f)
continue;
pushup(j,y,x);
}
for(int i=x;i<=n;i+=lowbit(i))
c[i]+=y;
return;
}
long long sum(int x)
{
long long r=0;
for(int i=x;i;i-=i&-i)
r+=c[i];
return r;
}
void dfs(int now,int fa)
{
in[now]=++tst;
pushup(tst,v[now],tst);
for(int i=head[now];i;i=Next[i])
{
int j=vet[i];
if(j==fa)
continue;
dfs(j,now);
}
out[now]=tst;
return;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>root;
for(int i=1;i<=n;i++)
cin>>v[i];
for(int i=1;i<=n-1;i++)
{
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
dfs(root,0);
for(int i=1;i<=m;i++)
{
int op,x,y;
cin>>op>>x;
if(op==1)
{
cin>>y;
pushup(in[x],y,in[x]);
}
else
{
int l=in[x],r=out[x];
cout<<sum(r)-sum(l-1)<<'\n';
}
}
return 0;
}