一个很裸的树链剖分模板。注意一下数据范围,有的地方要开longlong,这就是唯一的陷阱了。
# include<iostream>
# include<cstdio>
# include<cmath>
# include<algorithm>
using std::max;
using std::min;
const int mn = 100005;
typedef long long LL;
struct edge{int to,next;};
edge e[mn*2];
int edge_max,head[mn];
void add(int x,int y)
{
e[++edge_max].to=y;
e[edge_max].next=head[x];
head[x]=edge_max;
}
int n,m;
int val[mn];
int fa[mn],siz[mn];
void dfs1(int x)
{
siz[x]=1;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[x])
continue;
fa[v]=x;
dfs1(v);
siz[x]+=siz[v];
}
}
int tot,id[mn],bl[mn],mx[mn];
void dfs2(int x,int chain)
{
int k=0;
++tot;
id[x]=mx[x]=tot;
bl[x]=chain;
for(int i=head[x];i;i=e[i].next)
{
if(e[i].to!=fa[x] && siz[e[i].to]>siz[k])
k=e[i].to;
}
if(k==0)
return ;
dfs2(k,chain);
mx[x]=max(mx[x],mx[k]);
for(int i=head[x];i;i=e[i].next)
{
if(fa[x]!=e[i].to && e[i].to!=k)
{
dfs2(e[i].to,e[i].to);
mx[x]=max(mx[x],mx[e[i].to]);
}
}
}
struct node{int l,r;LL sum,tag;};
node tr[mn*4];
inline void pushdown(int cur)
{
if(tr[cur].tag && tr[cur].l!=tr[cur].r)
{
tr[cur<<1].tag+=tr[cur].tag;
tr[cur<<1|1].tag+=tr[cur].tag;
tr[cur<<1].sum+=(tr[cur<<1].r-tr[cur<<1].l+1)*tr[cur].tag;
tr[cur<<1|1].sum+=(tr[cur<<1|1].r-tr[cur<<1|1].l+1)*tr[cur].tag;
tr[cur].tag=0;
}
}
void build(int l,int r,int cur)
{
tr[cur].l=l,tr[cur].r=r;
if(l==r)
{
return ;
}
int mid=l+r>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
}
void update(int cur,int l,int r,LL x)//此处要开longlong防止下面爆掉
{
if(tr[cur].r<l || tr[cur].l>r)
return ;
pushdown(cur);
if(tr[cur].l>=l && tr[cur].r<=r)
{
tr[cur].sum+=(tr[cur].r-tr[cur].l+1)*x;//就是这里容易爆掉
tr[cur].tag+=x;
return ;
}
update(cur<<1,l,r,x);
update(cur<<1|1,l,r,x);
tr[cur].sum=tr[cur<<1].sum+tr[cur<<1|1].sum;
}
LL qsum(int cur,int l,int r)
{
if(tr[cur].r<l || tr[cur].l>r)
return 0;
pushdown(cur);
if(tr[cur].l>=l && tr[cur].r<=r)
return tr[cur].sum;
LL tmp=0;
tmp+=qsum(cur<<1,l,r);
tmp+=qsum(cur<<1|1,l,r);
tr[cur].sum=tr[cur<<1].sum+tr[cur<<1|1].sum;
return tmp;
}
void querry(int x)
{
LL ans=0;
while(bl[x]!=1)
{
ans+=qsum(1,id[bl[x]],id[x]);
x=fa[bl[x]];
}
ans+=qsum(1,1,id[x]);
printf("%lld\n",ans);
}
int main()
{
int opt,x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(1);
dfs2(1,1);
build(1,n,1);
for(int i=1;i<=n;i++)
update(1,id[i],id[i],val[i]);
for(int i=1;i<=m;i++)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d%d",&x,&y);
update(1,id[x],id[x],y*1ll);
}
else if(opt==2)
{
scanf("%d%d",&x,&y);
update(1,id[x],mx[x],y*1ll);
}
else {
scanf("%d",&x);
querry(x);
}
}
return 0;
}