• P3369 【模板】普通平衡树 (splay 模板)


    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    插入x数

    删除x数(若有多个相同的数,因只删除一个)

    查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

    查询排名为x的数

    求x的前驱(前驱定义为小于x,且最大的数)

    求x的后继(后继定义为大于x,且最小的数)
    输入输出格式

    输入格式:
    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 leq opt leq 6 1≤opt≤6 )

    输出格式:
    对于操作3,4,5,6每行输出一个数,表示对应答案

    输入输出样例

    输入样例#1:
    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598
    输出样例#1:
    106465
    84185
    492737
    说明

    时空限制:1000ms,128M

    n的数据范围:n≤100000

    code:

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<ctime>
    using namespace std;
    
    const int MAX=200010;
    
    int n,opt,x,root,sz;
    int node[MAX][2],size[MAX],fa[MAX],cnt[MAX],key[MAX];
    
    inline void clear(int x) {
        node[x][1]=node[x][0]=size[x]=fa[x]=cnt[x]=key[x]=0;
    }
    
    inline bool get(int x) {
        return node[fa[x]][1]==x;
    }
    
    inline void update(int x){
        if(x) {
            size[x]=cnt[x];
            if(node[x][1]) size[x]+=size[node[x][1]];
            if(node[x][0]) size[x]+=size[node[x][0]];
        }
    }
    
    inline void rotate(int x) {
        int old=fa[x],oldf=fa[old],which=get(x);
        node[old][which]=node[x][which^1]; fa[node[old][which]]=old;
        fa[old]=x; node[x][which^1]=old;
        fa[x]=oldf;
        if(oldf) node[oldf][node[oldf][1]==old]=x;
        update(old);update(x);
    }
    
    inline void splay(int x) {
        for(int f;f=fa[x];rotate(x))
            if(fa[f]){
                if(get(x)==get(f)) rotate(f);
                else rotate(x);
            }   
        root=x;
    }
    
    inline void insert(int x) {
        if(!root) {
            sz++;root=sz;
            node[sz][0]=node[sz][1]=fa[sz]=0;
            size[sz]=cnt[sz]=1;
            key[sz]=x;
            return ;
        }
        int now=root,f=0;
        while(1) {
            if(key[now]==x) {
                cnt[now]++;update(now);update(f);splay(now);break;
            }
            f=now;
            now=node[now][key[now]<x];
            if(now==0) {
                sz++;
                node[sz][0]=node[sz][1]=0;
                size[sz]=cnt[sz]=1;
                fa[sz]=f;key[sz]=x;
                node[f][key[f]<x]=sz;
                update(f);
                splay(sz);//为pre和next做准备 
                break;
            }
        }
    }
    
    inline int find1(int x) {
        int ans=0,now=root;
        while(1){
            if(x<key[now]) now=node[now][0];
            else {
                ans+=node[now][0]?size[node[now][0]]:0;
                if(x==key[now]) {
                    splay(now);
                    return ans+1;
                }
                else {
                    ans+=cnt[now];
                    now=node[now][1];
                }
            }
        }
    }
    
    inline int find2(int x) {
        int now=root;
        while(1){
            if(node[now][0]&&x<=size[node[now][0]]) 
                now=node[now][0];
            else {
                int temp=(node[now][0]?size[node[now][0]]:0)+cnt[now];
                if(x<=temp) return key[now];
                x-=temp,now=node[now][1];
            }
        }
    }
    
    inline int pre() {
        int now=node[root][0];
        while(node[now][1]) now=node[now][1];
        return now;
    }
    
    inline int next() {
        int now=node[root][1];
        while(node[now][0]) now=node[now][0];
        return now;
    }
    
    inline void del(int x) {
        find1(x);
        if(cnt[root]>1) {
            cnt[root]--;
            update(root);
        }
        else if(!node[root][0]&&!node[root][1]) {
            clear(root);root=0;
        }
        else if(!node[root][0]) {
            int old=root;
            root=node[root][1];
            fa[root]=0;
            clear(old);
        }
        else if(!node[root][1]) {
            int old=root;
            root=node[root][0];
            fa[root]=0;
            clear(old);
        }
        else {
            int lbig=pre(),old=root;
            splay(lbig);
            node[root][1]=node[old][1];
            fa[node[old][1]]=root;
            clear(old);
            update(root);
        }
        return ;
    }
    
    int main() {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {
            scanf("%d %d",&opt,&x);
            switch(opt) {
                case 1:insert(x);break;
                case 2:del(x);break;
                case 3:printf("%d
    ",find1(x));break;
                case 4:printf("%d
    ",find2(x));break;
                case 5:insert(x);printf("%d
    ",key[pre()]);del(x);break;
                case 6:insert(x);printf("%d
    ",key[next()]);del(x);break;   
            }
        }
        return 0;
    }
    版权声明:本文为博主原创文章,未经博主允许不得转载。 博主:https://www.cnblogs.com/Menteur-Hxy/
  • 相关阅读:
    Qt5."Clang Code Model"一些设置
    基于element表格的合并多个行实例
    vue中,基于echarts 地图实现一个人才回流的大数据展示效果
    vue2.0 子组件props接受父组件传递的值,能不能修改的问题整理
    vue调用组件,组件回调给data中的数组赋值,报错Invalid prop type check failed for prop value. Expecte
    vue,基于element的tree组件封装
    vue父子组件相互传值的实例
    基于vant实现一个问卷调查
    css3实现倾斜转动的转盘
    0801 am使用tp框架对数据库增删改查
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9248022.html
Copyright © 2020-2023  润新知