题意
给你一颗以 为根有
个节点的树,每个节点有一个点权。给你
次操作 ,操作有两种类型:
表示将节点
的权值加上
;
表示求以
为根的子树上所有节点的和(包括
节点);
分析
我们可以通过 序将一整棵子树上映射到序列中连续的一段上。所以问题就变成了,单点修改,区间和查询。直接用树状数组维护就好了。
代码
#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;
}

京公网安备 11010502036488号