zoukankan      html  css  js  c++  java
  • loj #107. 维护全序集

    #107. 维护全序集

    题目描述

    这是一道模板题,其数据比「普通平衡树」更强。

    如未特别说明,以下所有数据均为整数。

    维护一个多重集 S SS ,初始为空,有以下几种操作:

    1. 把 x xx 加入 S SS
    2. 删除 S SS 中的一个 x xx,保证删除的 x xx 一定存在
    3. 求 S SS 中第 k kk 小
    4. 求 S SS 中有多少个元素小于 x xx
    5. 求 S SS 中小于 x xx 的最大数
    6. 求 S SS 中大于 x xx 的最小数

    操作共 n nn 次。

    输入格式

    第一行一个整数 n nn,表示共有 n nn 次操作 。

    接下来 n nn 行,每行为以下几种格式之一 :

    • 0 x,把 x xx 加入 S SS
    • 1 x,删除 S SS 中的一个 x xx,保证删除的数在 S SS 中一定存在
    • 2 k,求 S SS 中第 k kk 小的数,保证要求的数在 S SS 中一定存在
    • 3 x,求 S SS 中有多少个数小于 x xx
    • 4 x,求 S SS 中小于 x xx 的最大数,如果不存在,输出 −1 -11
    • 5 x,求 S SS 中大于 x xx 的最小数,如果不存在,输出 −1 -11

    输出格式

    对于每次询问,输出单独一行表示答案。

    样例

    样例输入

    5
    0 3
    0 4
    2 2
    1 4
    3 3

    样例输出

    4
    0

    数据范围与提示

    1≤n≤3×105,0≤x≤109 1 leq n leq 3 imes 10 ^ 5, 0 leq x leq 10 ^ 91n3×105​​,0x109​​

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define INF 0x7fffffff
    #define maxn 400010
    using namespace std;
    int m,rt,son[maxn][2],fa[maxn],val[maxn],cnt[maxn],sz[maxn],size;
    void update(int x){
        sz[x]=sz[son[x][1]]+sz[son[x][0]]+cnt[x];
    }
    void rotate(int x,int &k){
        int y=fa[x],z=fa[fa[x]],l,r;
        if(son[y][0]==x)l=0;else l=1;r=l^1;
        if(y==k)k=x;
        else son[z][son[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
        son[y][l]=son[x][r];son[x][r]=y;
        update(y);update(x);
    }
    void splay(int x,int &k){
        while(x!=k){
            int y=fa[x],z=fa[fa[x]];
            if(y!=k){
                if((son[z][0]==y)^(son[y][0]==x))rotate(x,k);
                else rotate(y,k);
            }
            rotate(x,k);
        }
    }
    void Insert(int v){
        int y=0,k=rt;
        while(k&&val[k]!=v)y=k,k=son[k][v>val[k]];
        if(k)cnt[k]++;
        else {
            k=++size;
            cnt[k]=sz[k]=1;
            fa[k]=y;val[k]=v;
            if(y)son[y][v>val[y]]=k;
        }
        splay(k,rt);
    }
    int find2(int x){
        x++;int k=rt;
        if(sz[k]<x)return 0;
        while(1){
            if(sz[son[k][0]]<x&&sz[son[k][0]]+cnt[k]>=x)return k;
            if(sz[son[k][0]]>=x)k=son[k][0];
            else x-=sz[son[k][0]]+cnt[k],k=son[k][1];
        }
        return k;
    }
    void find1(int x){
        int k=rt;if(!k)return;
        while(son[k][x>val[k]]&&val[k]!=x)
            k=son[k][x>val[k]];
        splay(k,rt);
    }
    int nxt(int x,int f){
        find1(x);//if(!rt)return 0;
        if((val[rt]>x&&f)||(val[rt]<x&&!f))return rt;
        int k=son[rt][f];
        while(son[k][f^1])k=son[k][f^1];
        return k;
    }
    void del(int v){
        find1(v);
        int x=rt,k;
        if(cnt[rt]>1){cnt[rt]--;sz[rt]--;return;}
        if(son[rt][0]*son[rt][1]==0){
            rt=son[rt][0]+son[rt][1];
        }
        else {
            k=son[rt][1];
            while(son[k][0])k=son[k][0];sz[k]+=sz[son[x][0]];
            fa[son[x][0]]=k;
            son[k][0]=son[x][0];rt=son[x][1];
        }
        fa[rt]=0;splay(k,rt);
    }
    void debug(){
        printf("%d ",val[rt]);
        
    }
    int main(){
        scanf("%d",&m);
        Insert(0x7fffffff);Insert(-0x7fffffff);
        int op,x;
        while(m--){
            scanf("%d%d",&op,&x);
            if(op==0)Insert(x);
            if(op==1)del(x);
            if(op==2)printf("%d
    ",val[find2(x)]);
            if(op==3){
                find1(x);
                int ans=sz[son[rt][0]]-1;
                if(val[rt]<x)ans+=cnt[rt];
                printf("%d
    ",ans);
            }
            if(op==4){
                int w=val[nxt(x,0)];
                if(w==INF||w==-INF)puts("-1");
                else printf("%d
    ",w);
            }
            if(op==5){
                int w=val[nxt(x,1)];
                if(w==INF||w==-INF)puts("-1");
                else printf("%d
    ",w);
            }
        }
        return 0;
    }
  • 相关阅读:
    Vscode 隐藏 工作区中的目录
    java 中 静态泛型方法书写
    Vscode 配置 maven debug
    vscode 配置 java utf-8 编码
    node.js 设置 淘宝 镜像
    vscode 注册表
    ESET Smart Security 6 – 免费60天(SG)
    WIN-8“内置管理员无法激活此应用”问题
    怎样更新PE内的工具
    使用Setup安装Windows8 RTM方法
  • 原文地址:https://www.cnblogs.com/thmyl/p/8971773.html
Copyright © 2011-2022 走看看