把 n n n 个点按照深度的奇偶性分类,
如果 i i i 的深度为奇数,我们令 f l a g [ i ] = 1 flag[i]=1 flag[i]=1。
如果 i i i 的深度为偶数,我们令 f l a g [ i ] = − 1 flag[i]=-1 flag[i]=−1。
对于修改操作
我们给以 x x x 为根的那整棵子树的每个点加上 v a l ∗ f l a g [ x ] val*flag[x] val∗flag[x],
这可以用DFS序+树状数组在 O ( l o g n ) O(logn) O(logn) 的时间复杂度内解决。
对于询问操作
我们在树状数组中算出 x x x 的权值 v a l val val,然后 x x x 的实际权值为 a [ x ] + v a l ∗ f l a g [ x ] a[x]+val*flag[x] a[x]+val∗flag[x]。
代码
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int a[100010],v[100010],hd[100010],l[100010],r[1000010],flag[1000010],tree[1000010];
int n,m,x,y,c,val,tot,dep;
struct node
{
int x,to,next;
}map[1000010];
void ljb(int x,int y)
{
map[++tot].x=x;
map[tot].to=y;
map[tot].next=hd[x];
hd[x]=tot;
}
int lowbit(int x)
{
return x&-x;
}
void sum(int x,int w) //修改
{
while(x<=n)
{
tree[x]+=w;
x+=lowbit(x);
}
}
int findd(int x) //查询
{
int ans=0;
while(x>=1)
{
ans+=tree[x];
x-=lowbit(x);
}
return ans;
}
void dfsdep(int x,int fa) //求DFS序
{
dep++; //深度不断++
l[x]=dep; //自己的深度
flag[x]=-flag[fa]; //变换flag
for(int i=hd[x]; i; i=map[i].next)
{
if(map[i].to==fa)
continue;
dfsdep(map[i].to,x);
}
r[x]=dep; //自己的子树的最大深度位置
}
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
cin>>a[i];
for(int i=1; i<=n-1; i++)
{
cin>>x>>y;
ljb(x,y);
}
flag[0]=-1; //让第一个等于 1
dfsdep(1,0);
for(int i=1; i<=m; i++)
{
cin>>c;
if(c==1)
{
cin>>x>>val;
sum(l[x],val*flag[x]); //往后差分
sum(r[x]+1,-val*flag[x]);
}
if(c==2)
{
cin>>x;
cout<<a[x]+findd(l[x])*flag[x]<<endl;
}
}
return 0;
}