#include<bits/stdc++.h>
using namespace std;
int n,m;
struct data{
int l,r;
long long sum,mark;
}tree[400005];
int head[100005],nex[200005],to[200005],tp;
int a[100005],b[100005],siz[100005],dep[100005],fa[100005],son[100005],top[100005],pos[100005],cnt;
inline void add(int x,int y){
nex[++tp]=head[x];
head[x]=tp;
to[tp]=y;
}
void dfs1(int x,int father){
siz[x]=1;fa[x]=father;dep[x]=dep[father]+1;
for(int i=head[x];i;i=nex[i]){
if(to[i]==father) continue;
dfs1(to[i],x);
siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[son[x]]) son[x]=to[i];
}
}
void dfs2(int x,int tp){
top[x]=tp;pos[x]=++cnt;b[cnt]=a[x];
if(!son[x]) return;
dfs2(son[x],tp);
for(int i=head[x];i;i=nex[i]){
if(to[i]==fa[x] || to[i]==son[x]) continue;
dfs2(to[i],to[i]);
}
}
inline void pushdown(int x){
if(!tree[x].mark) return;
if(tree[x].l==tree[x].r){
tree[x].mark=0;
return;
}
tree[x<<1].sum+=tree[x].mark*(tree[x<<1].r-tree[x<<1].l+1);
tree[x<<1|1].sum+=tree[x].mark*(tree[x<<1|1].r-tree[x<<1|1].l+1);
tree[x<<1].mark+=tree[x].mark;
tree[x<<1|1].mark+=tree[x].mark;
tree[x].mark=0;
}
void buildtree(int num,int l,int r){
tree[num].l=l;tree[num].r=r;
if(l==r){
tree[num].sum=b[l];
return;
}
int mid=l+r>>1;
buildtree(num<<1,l,mid);
buildtree(num<<1|1,mid+1,r);
tree[num].sum=tree[num<<1].sum+tree[num<<1|1].sum;
}
void Modify(int num,int x,int v){
pushdown(num);
if(tree[num].l==tree[num].r){
tree[num].sum+=v;
return;
}
int mid=tree[num].l+tree[num].r>>1;
if(x<=mid) Modify(num<<1,x,v);
else Modify(num<<1|1,x,v);
tree[num].sum=tree[num<<1].sum+tree[num<<1|1].sum;
}
void Modify(int num,int l,int r,int v){
pushdown(num);
if(tree[num].l==l && tree[num].r==r){
tree[num].sum+=1ll*(r-l+1)*v;
tree[num].mark+=v;
return;
}
int mid=tree[num].l+tree[num].r>>1;
if(mid>=r) Modify(num<<1,l,r,v);
else if(mid<l) Modify(num<<1|1,l,r,v);
else Modify(num<<1,l,mid,v),Modify(num<<1|1,mid+1,r,v);
tree[num].sum=tree[num<<1].sum+tree[num<<1|1].sum;
}
long long Query(int num,int l,int r){
pushdown(num);
if(tree[num].l==l && tree[num].r==r) return tree[num].sum;
int mid=tree[num].l+tree[num].r>>1;
if(mid>=r) return Query(num<<1,l,r);
else if(mid<l) return Query(num<<1|1,l,r);
else return Query(num<<1,l,mid)+Query(num<<1|1,mid+1,r);
}
inline long long Query(int x){
long long re=0;
while(top[x]!=1){
re+=Query(1,pos[top[x]],pos[x]);
x=fa[top[x]];
}
re+=Query(1,pos[top[x]],pos[x]);
return re;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs1(1,0);dfs2(1,1);
buildtree(1,1,n);
while(m--){
int opt;
scanf("%d",&opt);
switch(opt){
case 1:{
int x,v;
scanf("%d%d",&x,&v);
Modify(1,pos[x],v);
break;
}
case 2:{
int x,v;
scanf("%d%d",&x,&v);
Modify(1,pos[x],pos[x]+siz[x]-1,v);
break;
}
case 3:{
int x;
scanf("%d",&x);
printf("%lld\n",Query(x));
break;
}
}
}
return 0;
}
【bzoj 4034】树上操作(树链剖分)
最新推荐文章于 2022-07-15 00:11:01 发布