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
",q.val[x]+add);
            }
            else if(s[1]=='2')
            {
                scanf("%d",&x);
                x=find(x);
                printf("%d
",q.val[x]+add);
            }
            else printf("%d
",Q.val[F[0]]+add);
        }
    }
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8391122.html