裸的链剖+dfs序
需要注意的是tag也要用ll,不要怕费空间或者超时,出题人一般(注意是一般)不会卡常,因为这个调了半个小时
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int N=200010;
ll qx;
int n,m,te,sz;
int size[N],head[N],tp[N],fa[N],son[N],tree[N],num[N],leaf[N];
struct edge{
int u,v,next;
}e[400010];
struct seg{
int l,r;
ll val,tag;
}tr[1000010];
inline int F()
{
register int aa,bb;register char ch;
while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
while(ch=getchar(),ch<='9'&&ch>='0')aa=(aa<<3)+(aa<<1)+ch-'0';return bb?aa:-aa;
}
void clear()
{
memset(head,0,sizeof(head));
memset(son,0,sizeof(son));
size[0]=0;fa[1]=1,sz=0;
}
void add(int u,int v)
{
e[++te].u=u;
e[te].v=v;
e[te].next=head[u];
head[u]=te;
}
void dfs1(int x)
{
size[x]=1;
for (int i=head[x];i;i=e[i].next)
{
int v=e[i].v;
if (v==fa[x])continue;
fa[v]=x;
dfs1(v);
size[x]+=size[v];
if (size[v]>size[son[x]])son[x]=v;
}
}
void dfs2(int x,int chain)
{
num[x]=++sz;
// cout<<x<<' '<<sz<<endl;
tp[x]=chain;
if (!son[x])return;
dfs2(son[x],chain);
for (int i=head[x];i;i=e[i].next)
{
int v=e[i].v;
if (v==fa[x]||v==son[x])continue;
dfs2(v,v);
}
}
void pushdown(int x)
{
if (!tr[x].tag||tr[x].l==tr[x].r)return;
int mid=(tr[x].l+tr[x].r)>>1;
tr[x<<1].val+=(ll)(mid-tr[x].l+1)*tr[x].tag;
tr[x<<1].tag+=tr[x].tag;
tr[x<<1|1].val+=(ll)(tr[x].r-mid)*tr[x].tag;
tr[x<<1|1].tag+=tr[x].tag;
tr[x].tag=0;
}
void updata(int k){tr[k].val=tr[k<<1].val+tr[k<<1|1].val;}
void build(int x,int l,int r)
{
tr[x].l=l,tr[x].r=r,tr[x].tag=0;
if (l==r){tr[x].val=1ll*leaf[tree[l]];return;}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
updata(x);
}
void change(int k,int x,int y,int z)
{
pushdown(k);
int l=tr[k].l,r=tr[k].r;
// cout<<k<<' '<<x<<' '<<y<<' '<<l<<' '<<r<<endl;
if (x<=l&&r<=y)
{
tr[k].val+=(ll)(r-l+1)*z;
tr[k].tag=z;
return;
}
int mid=(l+r)>>1;
if (x<=mid)change(k<<1,x,y,z);
if (y>mid)change(k<<1|1,x,y,z);
updata(k);
}
void query(int k,int x,int y)
{
pushdown(k);
int l=tr[k].l,r=tr[k].r;
if (x<=l&&r<=y)
{
// cout<<l<<' '<<r<<' '<<x<<' '<<y<<' '<<tr[k].val<<endl;
qx+=tr[k].val;
return;
}
int mid=(l+r)>>1;
if (x<=mid)query(k<<1,x,y);
if (y>mid)query(k<<1|1,x,y);
updata(k);
}
ll solvequery(int x)
{
qx=0;
while(tp[x]!=1)
{
query(1,num[tp[x]],num[x]);
// cout<<x<<' '<<tp[x]<<' '<<fa[tp[x]]<<' '<<qx<<endl;
x=fa[tp[x]];
}
query(1,1,num[x]);
// cout<<num[x]<<' '<<qx<<endl;
return qx;
}
int main()
{
clear();
int a,x,y,u,v,op;
n=F(),m=F();
for (int i=1;i<=n;i++)leaf[i]=F();
for (int i=1;i<n;++i)
u=F(),v=F(),add(u,v),add(v,u);
dfs1(1);
dfs2(1,1);
for (int i=1;i<=n;++i)
tree[num[i]]=i;
// cout<<endl<<endl;
// for (int i=1;i<=n;++i)
// cout<<num[i]<<' '<<tree[i]<<' '<<leaf[i]<<endl;
build(1,1,n);
// getchar();
for (int i=1;i<=m;++i)
{
op=F();
if (op==1)
x=F(),a=F(),change(1,num[x],num[x],a);
else if (op==2)
x=F(),a=F(),change(1,num[x],num[x]+size[x]-1,a);
else if (op==3)
x=F(),printf("%lld\n",solvequery(x));
// for (int i=1;i<=20;++i)
// cout<<tr[i].l<<' '<<tr[i].r<<' '<<tr[i].val<<' '<<tr[i].tag<<endl;
}
}