zoukankan      html  css  js  c++  java
  • BZOJ 2333: [SCOI2011]棘手的操作

    题目描述

    真的是个很棘手的操作。。

    注意每删除一个点,就需要clear一次。

    #include<complex>
    #include<cstdio>
    using namespace std;
    const int N=3e5+7;
    int n,m,rot,add;
    //add记录所有节点增加的权值 
    int q[N<<1];
    inline int qread()
    {
        int x=0,j=1;
        char ch=getchar();
        while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*j;
    }
    struct Leftist
    {
        int fat[N],son[N][2],key[N],dis[N],mark[N];
        void clear(int x)
        {
            fat[x]=son[x][1]=son[x][0]=0;
        }
        void PushDown(int x)
        {
            if(!mark[x])return;
            if(son[x][0])
            {
                key[son[x][0]]+=mark[x];
                mark[son[x][0]]+=mark[x];
            }
            if(son[x][1])
            {
                key[son[x][1]]+=mark[x];
                mark[son[x][1]]+=mark[x];
            }
            mark[x]=0;
        }
        int Merge(int a,int b)
        {
            if(!a || !b)return a+b;
            if(key[a]<key[b])swap(a,b);
            PushDown(a);
            son[a][1]=Merge(son[a][1],b);
            fat[son[a][1]]=a;
            if(dis[son[a][1]]>dis[son[a][0]])swap(son[a][1],son[a][0]);
            dis[a]=dis[son[a][1]]+1;
            return a;
        }
        int Sum(int x)
        {
            int res=0;
            while(x=fat[x])res+=mark[x];
            return res;
        }
        int Top(int x)
        {
            while(fat[x])x=fat[x];
            return x;
        }
        int Pop(int x)
        {
            PushDown(x);
            int q=fat[x],p=Merge(son[x][0],son[x][1]);
            if(q)son[q][son[q][1]==x]=p;
            fat[p]=q;
            while(q)
            {
                if(dis[son[q][1]]>dis[son[q][0]])
                    swap(son[q][1],son[q][0]);
                if(dis[q]==dis[son[q][1]]+1)return rot;
                dis[q]=dis[son[q][1]]+1;
                p=q;q=fat[q];
            }
            return p;
        }
        int AddPoint(int x,int v)
        {
            int t=Top(x);
            if(t==x)
                if(!son[x][1] && !son[x][0])
                {
                    key[x]+=v;
                    return x;
                }
                else
                    if(son[x][0])t=son[x][0];
                    else t=son[x][1];
            Pop(x);
            key[x]+=v+Sum(x);
            clear(x);
            return Merge(Top(t),x);
        }
        int Build()
        {
            int head=1,tail=0;
            for(int i=1;i<=n;i++)
                q[++tail]=i;
            int x,y;
            while(tail-head)
            {
                x=q[head++];y=q[head++];
                q[++tail]=Merge(x,y);
            }
            return q[head];
        }
    }t1,t2;
    //对于F3操作,需要把所有堆的根拿出来建一个新的堆 
    //新开一棵t2来维护这些点 
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            t1.key[i]=t2.key[i]=qread();
        rot=t2.Build();
        char c[5];int x,y,r1,r2;
        scanf("%d",&m);
        while(m--)
        {
            scanf("%s",c);
            if(c[0]=='U')
            {
                x=qread();y=qread();
                r1=t1.Top(x);r2=t1.Top(y);
                if(r1!=r2)
                {
                    int tmp=t1.Merge(r1,r2);
                    if(tmp==r1)t2.Pop(r2);
                    else t2.Pop(r1);
                    /*
                    合并时,若树a并到了b上,则将a从第二棵树中删除,反之则删除b 
                    被删去的点还是可能会成为最大值的,可它已经被删除了.... 
                    它再次成为最大值只有可能是在A1操作,将它再插入就好了 
                    */
                }
            }
            else if(c[0]=='A' && c[1]=='1')
            {
                x=qread();y=qread();
                rot=t2.Pop(t1.Top(x));
                int tmp=t1.AddPoint(x,y);
                t2.key[tmp]=t1.key[tmp];
                t2.clear(tmp);
                rot=t2.Merge(rot,tmp);
            }
            else if(c[0]=='A' && c[1]=='2')
            {
                x=qread();y=qread();
                r1=t1.Top(x);
                rot=t2.Pop(r1);
                //整个联通块都+y,不影响堆的性质,但mark不能及时下传,所以仍要把根删去后再插入 
                t1.key[r1]+=y;t1.mark[r1]+=y;
                t2.key[r1]=t1.key[r1];
                t2.clear(r1);
                rot=t2.Merge(r1,rot);
            }
            else if(c[0]=='A' && c[1]=='3')add+=qread();
            else if(c[0]=='F' && c[1]=='1')
            {
                x=qread();
                printf("%d
    ",t1.key[x]+add+t1.Sum(x));
            }
            else if(c[0]=='F' && c[1]=='2')
            {
                x=qread();
                printf("%d
    ",t1.key[t1.Top(x)]+add);
            }
            else printf("%d
    ",t2.key[rot]+add);
        }
        return 0;
    }
  • 相关阅读:
    ActiveMQ消息队列技术融合Spring
    ActiveMQ消息队列技术Demo
    网页静态化技术Freemaker
    Solr的基本语法
    Solr的页面展示以及高亮显示
    Solr的了解与配置
    Angular中上传图片到分布式文件服务器FastDFS上
    分布式文件服务器FastDFS的使用
    自我学习笔记01
    数组转换成List集合
  • 原文地址:https://www.cnblogs.com/LeTri/p/8670736.html
Copyright © 2011-2022 走看看