题意:维护一棵带点权的树,支持查询子树权值和,子树整体增值,换父亲
复习splay
刚开始做的时候智障了,这道题其实直接用splay维护出栈入栈序列就好了
#include<stdio.h>
struct edge{
int to,nex;
}e[200010];
#define ll long long
int fa[200010],ch[200010][2],siz[200010],nv[100010],h[100010],in[100010],out[100010],M,rt,tot;
ll v[200010],ad[200010],sum[200010];
#define ls ch[x][0]
#define rs ch[x][1]
void add(int a,int b){
tot++;
e[tot].to=b;
e[tot].nex=h[a];
h[a]=tot;
}
void dfs(int f,int x){
in[x]=++M;
for(int i=h[x];i;i=e[i].nex){
if(e[i].to!=f)dfs(x,e[i].to);
}
out[x]=++M;
}
void pushup(int x){
sum[x]=v[x]+sum[ls]+sum[rs];
siz[x]=siz[ls]+siz[rs]+1;
}
int build(int l,int r){
int mid=(l+r)>>1;
if(l<mid){
ch[mid][0]=build(l,mid-1);
fa[ch[mid][0]]=mid;
}
if(mid<r){
ch[mid][1]=build(mid+1,r);
fa[ch[mid][1]]=mid;
}
pushup(mid);
return mid;
}
void rot(int x){
int y,z,f,B;
y=fa[x];
z=fa[y];
if(y==rt)rt=x;
f=ch[y][0]==x;
B=ch[x][f];
fa[x]=z;
fa[y]=x;
if(B)fa[B]=y;
ch[x][f]=y;
ch[y][f^1]=B;
if(ch[z][0]==y)ch[z][0]=x;
if(ch[z][1]==y)ch[z][1]=x;
pushup(y);
pushup(x);
}
void plus(int x,ll d){
sum[x]+=siz[x]*d;
ad[x]+=d;
v[x]+=d;
}
void pushdown(int x){
if(ad[x]){
if(ls)plus(ls,ad[x]);
if(rs)plus(rs,ad[x]);
ad[x]=0;
}
}
void gao(int x){
if(fa[x])gao(fa[x]);
pushdown(x);
}
void splay(int x,int gl){
gao(x);
int y,z;
while(fa[x]!=gl){
y=fa[x];
z=fa[y];
if(z!=gl)rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x);
rot(x);
}
}
int presc(int x){
splay(x,0);
x=ls;
while(rs)x=rs;
return x;
}
int nexsc(int x){
splay(x,0);
x=rs;
while(ls)x=ls;
return x;
}
int sub(int x){
int p=presc(in[x]),n=nexsc(out[x]);
if(p==0){
if(n==0)return rt;
splay(n,0);
return ch[n][0];
}
splay(p,0);
if(n==0)return ch[p][1];
splay(n,p);
return ch[n][0];
}
ll query(int x){return sum[sub(x)]>>1;}
void modify(int x,ll v){plus(sub(x),v);}
void change(int x,int y){
int s=sub(x);
x=fa[s];
if(ls==s)ls=0;
if(rs==s)rs=0;
while(x){
pushup(x);
x=fa[x];
}
x=nexsc(in[y]);
splay(x,in[y]);
fa[s]=x;
ls=s;
while(x){
pushup(x);
x=fa[x];
}
}
int main(){
int n,m,i,x,y;
ll d;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",nv+i);
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(0,1);
for(i=1;i<=n;i++)v[in[i]]=v[out[i]]=nv[i];
rt=build(1,M);
while(m--){
scanf("%d",&i);
if(i==1){
scanf("%d",&x);
printf("%lld\n",query(x));
}
if(i==2){
scanf("%d%lld",&x,&d);
modify(x,d);
}
if(i==3){
scanf("%d%d",&x,&y);
change(x,y);
}
}
}