bzoj千题计划218:bzoj2333: [SCOI2011]棘手的操作
http://www.lydsy.com/JudgeOnline/problem.php?id=2333
上次那个是线段树,再发一个左偏树
维护两种左偏树
第一种是对每个联通块维护一个左偏树
第二种是对所有第一种左偏树的根节点维护一个左偏树
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 300001 /*void read(int &x) { x=0; int f=1; char c=getchar(); while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } x*=f; }*/ struct Leftist { int fa[N],lc[N],rc[N]; int dis[N]; int val[N],tag[N]; int st[N]; void addsingle(int x,int y) { if(!x) return; val[x]+=y; tag[x]+=y; } void down(int x) { if(!tag[x]) return; addsingle(lc[x],tag[x]); addsingle(rc[x],tag[x]); tag[x]=0; } void download(int x) { int top=0; for(int i=x;i;i=fa[i]) st[++top]=i; for(;top;--top) down(top); } int merge(int x,int y) { if(!x || !y) return x+y; if(val[x]<val[y]) swap(x,y); down(x); rc[x]=merge(rc[x],y); if(dis[lc[x]]<dis[rc[x]]) swap(lc[x],rc[x]); if(!rc[x]) dis[x]=0; else dis[x]=dis[rc[x]]+1; if(lc[x]) fa[lc[x]]=x; if(rc[x]) fa[rc[x]]=x; return x; } void del(int &root,int x) { int y=fa[x]; bool k= rc[y]==x; x=merge(lc[x],rc[x]); fa[x]=y; if(!y) { root=x; return; } if(k) rc[y]=x; else lc[y]=x; if(dis[lc[y]]<dis[rc[y]]) swap(lc[y],rc[y]); x=rc[y]; while(y && dis[y]!=dis[x]+1) { dis[y]=dis[x]+1; y=fa[y]; if(dis[lc[y]]<dis[rc[y]]) swap(lc[y],rc[y]); x=rc[y]; } } void push(int id,int &root,int x) { fa[id]=lc[id]=rc[id]=dis[id]=tag[id]=0; val[id]=x; root=merge(root,id); } }q,Q; int F[N]; int find(int i) { return F[i]==i ? i : F[i]=find(F[i]); } int main() { int n,m,x,y; char s[4]; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&x); q.push(i,F[i],x); Q.push(i,F[0],x); } scanf("%d",&m); int add=0; while(m--) { scanf("%s",s); if(s[0]=='U') { scanf("%d",&x); scanf("%d",&y); x=find(x); y=find(y); if(x==y) continue; Q.del(F[0],x); Q.del(F[0],y); F[x]=F[y]=q.merge(x,y); x=F[x]; Q.push(x,F[0],q.val[x]); } else if(s[0]=='A') { if(s[1]=='1') { scanf("%d",&x); scanf("%d",&y); find(x); Q.del(F[0],F[x]); q.download(x); int tmp=q.val[x]; q.del(F[x],x); int z=F[x]; if(z) { F[z]=z; q.push(x,F[z],tmp+y); F[x]=F[z]; } else q.push(x,F[x],tmp+y); Q.push(F[x],F[0],q.val[F[x]]); } else if(s[1]=='2') { scanf("%d",&x); scanf("%d",&y); x=find(x); Q.del(F[0],x); q.addsingle(x,y); Q.push(x,F[0],q.val[x]); } else { scanf("%d",&x); add+=x; } } else { if(s[1]=='1') { scanf("%d",&x); q.download(x); printf("%d\n",q.val[x]+add); } else if(s[1]=='2') { scanf("%d",&x); x=find(x); printf("%d\n",q.val[x]+add); } else printf("%d\n",Q.val[F[0]]+add); } } }