文章总数30祭+CF383C Propagating tree
题意:给出一棵n个结点的树,每个结点有一个权值,有m个操作,一个是给x结点加上val,并且给x的子节点加上-val(这里有传递性,子节点还要给其子节点加上-(-val))。另一个操作是查询某个结点的值。
还有,根是1
?
DFS序
把树拍扁拍成一个链
然后在上面用线段树维护
维护啥?
LZT(Lazzy Tag)
啥?没错,这题就是这么水,只用维护LZT即可
单点查询+区间修改。
单点查询so easy,但是区间修改…
定义两个LZT,LZT1和LZT2
记录链上每个点的深度的奇偶性
LZT1[i]表示第i个状态的给深度为奇数的点要加的值
LZT2[i]也同理
然后就好写了
std:
#include<bits/stdc++.h>
using namespace std;
const int N=500005;
int n,m;
int col[N];
int hed[N*2],tal[N*2],nxt[N*2],cnt=0;
int k[N];
int c[N];
int ll[N];
int rr[N];
int opt=0;
int t[N*10];
int dis[N];
int LZT1[N*10]={0};//LZT=0:不加不减 LZT>0 加 LZT<0 减
int LZT2[N*10]={0};
int sec[N*10]={0};//sec=0:偶数层的 sec=1:奇数层的 sec=2:即有奇数层的也有偶数层的
//root=1
void push_up(int num){
t[num]=t[num<<1]+t[num<<1|1];
}
void push_down(int l,int r,int num){
LZT1[num<<1]+=LZT1[num];
LZT1[num<<1|1]+=LZT1[num];
LZT1[num]=0;
LZT2[num<<1]+=LZT2[num];
LZT2[num<<1|1]+=LZT2[num];
LZT2[num]=0;
}
void addege(int x,int y){
cnt++;
tal[cnt]=y;
nxt[cnt]=hed[x];
hed[x]=cnt;
}
void dfs(int x,int father,int deep){
k[++opt]=x;
c[opt]=col[x];
ll[x]=opt;
dis[opt]=deep;
for(int i=hed[x];i;i=nxt[i]){
int v=tal[i];
if(v==father) continue;
dfs(v,x,deep+1);
}
k[++opt]=x;
c[opt]=col[x];
rr[x]=opt;
dis[opt]=deep;
}
void build(int l,int r,int num){
if(l==r){
LZT1[num]=0;
LZT2[num]=0;
t[num]=c[l];
sec[num]=dis[l]%2;
if(sec[num]==0) LZT2[num]=c[l];
else LZT1[num]=c[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,num<<1);
build(mid+1,r,num<<1|1);
t[num]=t[num<<1]+t[num<<1|1];
if(sec[num<<1]==sec[num<<1|1]) sec[num]=sec[num<<1];
else sec[num]=2;
LZT1[num]=0;
LZT2[num]=0;
}
void add(int l,int r,int num,int L,int R,int v,int u){
if(l>R||r<L) return;
if(l>=L&&r<=R){
if(u==1) LZT1[num]+=v,LZT2[num]-=v;
else LZT1[num]-=v,LZT2[num]+=v;
return;
}
int mid=(l+r)>>1;
push_down(l,r,num);
add(l,mid,num<<1,L,R,v,u);
add(mid+1,r,num<<1|1,L,R,v,u);
}
int ask(int l,int r,int num,int X){
// printf("** (%d-%d):%d %d**\n",l,r,num,X);
if(l>X||r<X) return 0;
if(l==r&&r==X){
// for(int i=1;i<=50;i++) printf("%d %d **\n",LZT1[i],LZT2[i]);
if(dis[X]%2==0) return LZT2[num];
else return LZT1[num];
}
push_down(l,r,num);
int mid=(l+r)>>1;
if(mid>=X) return ask(l,mid,num<<1,X);
else return ask(mid+1,r,num<<1|1,X);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&col[i]);
}
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
addege(a,b);
addege(b,a);
}
dfs(1,0,1);
build(1,2*n,1);
for(int i=1;i<=m;i++){
int opt,a,b;
scanf("%d",&opt);
if(opt==1){
scanf("%d%d",&a,&b);
int L=ll[a],R=rr[a];
add(1,2*n,1,L,R,b,dis[L]%2);
}
else{
//for(int i=1;i<=50;i++) printf("%d %d\n",LZT1[i],LZT2[i]);
scanf("%d",&a);
int X=ll[a];
printf("%d\n",ask(1,2*n,1,X));
}
}
return 0;
}