树上区间加和区间求和
样例没过,都是负,但数字没炸
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
int n,m;ll tr1[N],tr2[N];
int h[N],e[N],ne[N],idx,w[N];
int din[N],dout[N],id;
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int lowbit(int x){
return x&(-x);
}
void add(ll tr[],int x,ll c){
for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}
ll sum(ll tr[],int x){
ll res=0;
for(int i=x;i;i-=lowbit(i)) res+=tr[i];
return res;
}
ll query(int x){
return sum(tr1,x)*(x+1)-sum(tr2,x);
}
void modify(int x,int y,ll k){
add(tr1,x,k);add(tr1,y+1,-k);
add(tr2,x,k*x);add(tr2,y+1,-k*(y+1));
}
void dfs(int x,int fa){
din[x]=++id;
for(int i=h[x];~i;i=ne[i]){
int j=e[i];
if(j==fa) continue;
dfs(j,x);
}
dout[x]=++id;
}
int rt;
signed main(){
memset(h,-1,sizeof(h));
scanf("%d%d%d",&n,&m,&rt);
for(int i=1;i<=n;i++) scanf("%lld",&w[i]);
for(int i=1;i<n;i++){
int a,b;scanf("%d%d",&a,&b);
add(a,b);add(b,a);
}
dfs(rt,-1);
for(int i=1;i<=n;i++) modify(din[i],din[i],w[i]);//使用函数封装,防止出错
while(m--){
int opt,x;ll y;
scanf("%d%d",&opt,&x);
if(opt==1){
scanf("%lld",&y);
modify(din[x],dout[x],y);
}
else printf("%lld\n",query(dout[x])-query(din[x]-1));
}
return 0;
}