题意:维护一棵带点权的树,支持查询子树权值和,子树整体增值,换父亲
复习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); } } }
时间: 2024-10-15 23:55:07