题意
给你一颗以 为根有 个节点的树,每个节点有一个点权。给你 次操作 ,操作有两种类型: 表示将节点 的权值加上 ;
表示求以 为根的子树上所有节点的和(包括 节点);
分析
我们可以通过 序将一整棵子树上映射到序列中连续的一段上。所以问题就变成了,单点修改,区间和查询。直接用树状数组维护就好了。
代码
#include<bits/stdc++.h> #define ll long long const int N=1e5+5,INF=0x3f3f3f3f,mod=998244353; using namespace std; int n,m,rt,cnt; int T[N],head[N],l[N],r[N],a[N]; struct node { int nxt,to; }e[N<<1]; inline int read() { register int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar(); return x*f; } int qpow(int a,int b) { int ans=1; while(b){if(b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans; } void add(int u,int v) { e[++cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } int lowbit(int x) { return x&(-x); } void update(int x,int w) { while(x<N) { T[x]+=w; x+=lowbit(x); } } int query(int x) { int res=0; while(x) { res+=T[x]; x-=lowbit(x); } return res; } void dfs(int u,int ***]=++cnt; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(v==fa) continue ; dfs(v,u); } r[u]=cnt; } int main() { n=read();m=read(),rt=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<n;i++) { int u=read(),v=read(); add(u,v);add(v,u); } cnt=0; dfs(rt,0); for(int i=1;i<=n;i++) update(l[i],a[i]); while(m--) { int opt=read(); if(opt==1) { int x=read(),y=read(); update(l[x],y); } else { int x=read(); printf("%d\n",query(r[x])-query(l[x]-1)); } } return 0; }