• bzoj4864 [BeiJing 2017 Wc]神秘物质


    题目描述

    题解:

    splay维护区间最大最小值,以及相邻两项的最小差。

    因为向集合中加入元素不能缩小极差。

    还有,要换行。

    PE2次。

    代码:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    #define M 200050
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,m,e[N];
    const int inf = 0x3f3f3f3f;
    struct Splay
    {
        int mn[M],mx[M],v[M],Mn[M],L[M],R[M];
        int fa[M],ch[M][2],siz[M],rt,tot;
        Splay()
        {
            v[0]=Mn[0]=mn[0]=L[0]=R[0]=inf;
            tot = 0;
        }
        void update(int u)
        {
            int ls = ch[u][0],rs = ch[u][1];
            siz[u] = siz[ls]+siz[rs]+1;
            mn[u]=min(min(mn[ls],mn[rs]),v[u]);
            mx[u]=max(max(mx[ls],mx[rs]),v[u]);
            Mn[u]=inf;
            if(ls)Mn[u] = min(Mn[u],min(Mn[ls],abs(v[u]-R[ls])));
            if(rs)Mn[u] = min(Mn[u],min(Mn[rs],abs(v[u]-L[rs])));
            if(ls)L[u] = L[ls];
            else L[u]=v[u];
            if(rs)R[u] = R[rs];
            else R[u]=v[u];
        }
        void rotate(int x)
        {
            int y = fa[x],z = fa[y],k = (ch[y][1]==x);
            ch[y][k]=ch[x][!k],fa[ch[x][!k]]=y;
            ch[x][!k]=y,fa[y]=x;
            ch[z][ch[z][1]==y]=x,fa[x]=z;
            update(y),update(x);
        }
        void splay(int x,int goal)
        {
            while(fa[x]!=goal)
            {
                int y = fa[x],z = fa[y];
                if(z!=goal)
                    (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
                rotate(x);
            }
            if(!goal)rt=x;
        }
        int build(int l,int r,int f)
        {
            if(l>r)return 0;
            int mid = (l+r)>>1;
            int x = ++tot;
            fa[x]=f;
            L[x]=R[x]=v[x]=e[mid];
            Mn[x]=inf;
            ch[x][0]=build(l,mid-1,x);
            ch[x][1]=build(mid+1,r,x);
            update(x);
            return x;
        }
        int get_pnt(int x,int k)
        {
            int tmp = siz[ch[x][0]];
            if(k<=tmp)return get_pnt(ch[x][0],k);
            else if(k==tmp+1)return x;
            else return get_pnt(ch[x][1],k-1-tmp);
        }
        void Merge(int x,int d)
        {
            int x1 = get_pnt(rt,x);
            int x2 = get_pnt(rt,x+3);
            splay(x1,0);splay(x2,x1);
            x = ++tot;
            siz[x] = 1;
            fa[x] = x2;ch[x2][0] = x;
            v[x] = mn[x] = mx[x] = L[x] = R[x] = d;
            Mn[x] = inf;
            update(x2),update(x1);
        }
        void Insert(int x,int d)
        {
            int x1 = get_pnt(rt,x+1);
            int x2 = get_pnt(rt,x+2);
            splay(x1,0);splay(x2,x1);
            x = ++tot;
            siz[x] = 1;
            fa[x] = x2;ch[x2][0] = x;
            v[x] = mn[x] = mx[x] = L[x] = R[x] = d;
            Mn[x] = inf;
            update(x2),update(x1);
        }
        int Max(int x,int y)
        {
            x = get_pnt(rt,x);
            y = get_pnt(rt,y+2);
            splay(x,0);splay(y,x);
            return mx[ch[y][0]]-mn[ch[y][0]];
        }
        int Min(int x,int y)
        {
            x = get_pnt(rt,x);
            y = get_pnt(rt,y+2);
            splay(x,0);splay(y,x);
            return Mn[ch[y][0]];
        }
    }tr;
    char opt[10];
    int main()
    {
        n=rd(),m=rd();
        e[1]=e[n+2]=inf;
        for(int i=2;i<=n+1;i++)e[i]=rd();
        tr.rt = tr.build(1,n+2,0);
        for(int x,y,i=1;i<=m;i++)
        {
            scanf("%s",opt+1);
            x = rd(),y = rd();
            if(opt[2]=='e')
            {
                tr.Merge(x,y);
            }else if(opt[2]=='n')
            {
                tr.Insert(x,y);
            }else if(opt[2]=='a')
            {
                printf("%d
    ",tr.Max(x,y));
            }else
            {
                printf("%d
    ",tr.Min(x,y));
            }
        }
    //    puts("");
        return 0;
    }
  • 相关阅读:
    底层因为接受到操作系统信号而停止的解决
    C语言判断文件是否存在
    Linux磁盘设备文件(sda,sdb,sdc…)变化问题
    linux mysql 数据目录文件夹移动及所遇到的问题
    Linux Mysql如何移动MySQL数据库目录位置
    Linux 磁盘挂载和mount共享
    提高VS2010/VS2012编译速度
    C++[类设计] ini配置文件读写类config
    WIN32读写INI文件方法
    MS509Team----------------Cknife
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10161998.html
Copyright © 2020-2023  润新知