题如其名
树链剖分板子题
#include<bits/stdc++.h>
using namespace std;
#define lc (p<<1)
#define rc (p<<1|1)
typedef int INT;
#define int long long
const int N=2e5+100;
inline void read(int &x){
x=0;
char ch=getchar();
int f=1;
while(ch<'0'||ch>'9'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
struct Front_star{
int u,v,nxt;
}e[N*4];
int cnt=1;
int first[N]={};
void addedge(int u,int v){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].nxt=first[u];
first[u]=cnt;
}
void add(int u,int v){
addedge(u,v);
addedge(v,u);
}
int n,m;
int dep[N]={};
int siz[N]={};
int son[N]={};
int top[N]={};
int fa[N]={};
int tree[N]={};
int pre[N]={};
int idx=0;
struct Segment_Tree{
int sum,lson,rson,addlazy;
}T[N<<2];
void dfs1(int u,int fat,int depth){
// cout<<u<<" "<<'\n';
dep[u]=depth;
siz[u]=1;
fa[u]=fat;
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fat)continue;
dfs1(v,u,depth+1);
siz[u]+=siz[v];
if(!son[u]||siz[son[u]]<siz[v]){
son[u]=v;
}
}
}
void dfs2(int u,int tp){
// cout<<u<<" "<<'\n';
top[u]=tp;
tree[u]=++idx;
pre[idx]=u;
if(!son[u])return;
dfs2(son[u],tp);
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
int val[N]={};
void pushup(int p){
T[p].sum=T[lc].sum+T[rc].sum;
}
void pushdown(int p){
if(T[p].addlazy){
T[lc].sum+=(T[lc].rson-T[lc].lson+1)*T[p].addlazy;
T[rc].sum+=(T[rc].rson-T[rc].lson+1)*T[p].addlazy;
T[lc].addlazy+=T[p].addlazy;
T[rc].addlazy+=T[p].addlazy;
T[p].addlazy=0;
}
}
void build(int p,int l,int r){
T[p].lson=l;
T[p].rson=r;
if(l==r){
T[p].sum=val[pre[l]];
T[p].addlazy=0;
return;
}
int mid=(l+r)/2;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(p);
}
void update(int p,int dl,int dr,int val){
if(dl<=T[p].lson&&T[p].rson<=dr){
T[p].sum+=(T[p].rson-T[p].lson+1)*val;
T[p].addlazy+=val;
return;
}
pushdown(p);
int mid=(T[p].lson+T[p].rson)/2;
if(dl<=mid)update(lc,dl,dr,val);
if(mid<dr)update(rc,dl,dr,val);
pushup(p);
}
int query(int p,int dl,int dr){
int ret=0;
if(dl<=T[p].lson&&T[p].rson<=dr){
return T[p].sum;
}
pushdown(p);
int mid=(T[p].lson+T[p].rson)/2;
if(dl<=mid)ret+=query(lc,dl,dr);
if(mid<dr) ret+=query(rc,dl,dr);
return ret;
}
int query_line(int x,int y){
int ret=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ret+=query(1,tree[top[x]],tree[x]);
x=fa[top[x]];
}
if(tree[x]>tree[y])swap(x,y);
ret+=query(1,tree[x],tree[y]);
return ret;
}
INT main(){
// freopen("P3178.c","r",stdin);
read(n);
read(m);
for(int i=1;i<=n;i++){
read(val[i]);
}
for(int i=1;i<n;i++){
int u,v;
read(u);
read(v);
add(u,v);
}
dfs1(1,0,1);
dfs2(1,1);
// for(int i=1;i<=n;i++)cout<<tree[i]<<" ";
build(1,1,n);
// cout<<query(1,1,n);
// cout<<"working"<<'\n';
while(m--){
int opt,x;
read(opt);
read(x);
if(opt==1){
int val;
read(val);
update(1,tree[x],tree[x],val);
}
else{
if(opt==2){
int val;
read(val);
update(1,tree[x],tree[x]+siz[x]-1,val);
}
else{
int sum=query_line(1,x);
cout<<sum<<'\n';
}
}
}
}