bzoj千题计划218:bzoj2333: [SCOI2011]棘手的操作

时间:2020-12-29 21:32:00

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]=;
} void download(int x)
{
int top=;
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]=;
else dis[x]=dis[rc[x]]+;
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]+)
{
dis[y]=dis[x]+;
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]=;
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[];
scanf("%d",&n);
for(int i=;i<=n;++i)
{
scanf("%d",&x);
q.push(i,F[i],x);
Q.push(i,F[],x);
}
scanf("%d",&m);
int add=;
while(m--)
{
scanf("%s",s);
if(s[]=='U')
{
scanf("%d",&x);
scanf("%d",&y);
x=find(x); y=find(y);
if(x==y) continue;
Q.del(F[],x);
Q.del(F[],y);
F[x]=F[y]=q.merge(x,y);
x=F[x];
Q.push(x,F[],q.val[x]);
}
else if(s[]=='A')
{
if(s[]=='')
{
scanf("%d",&x);
scanf("%d",&y);
find(x);
Q.del(F[],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[],q.val[F[x]]);
}
else if(s[]=='')
{
scanf("%d",&x);
scanf("%d",&y);
x=find(x);
Q.del(F[],x);
q.addsingle(x,y);
Q.push(x,F[],q.val[x]);
}
else
{
scanf("%d",&x);
add+=x;
}
}
else
{
if(s[]=='')
{
scanf("%d",&x);
q.download(x);
printf("%d\n",q.val[x]+add);
}
else if(s[]=='')
{
scanf("%d",&x);
x=find(x);
printf("%d\n",q.val[x]+add);
}
else printf("%d\n",Q.val[F[]]+add);
}
}
}