zoukankan      html  css  js  c++  java
  • [luogu] P3369 【模板】普通平衡树(splay)

    P3369 【模板】普通平衡树

    题目描述

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

    1. 插入 (x)
    2. 删除 (x) 数(若有多个相同的数,因只删除一个)
    3. 查询 (x) 数的排名(排名定义为比当前数小的数的个数 (+1) 。若有多个相同的数,因输出最小的排名)
    4. 查询排名为 (x) 的数
    5. (x) 的前驱(前驱定义为小于 (x),且最大的数)
    6. (x) 的后继(后继定义为大于 (x),且最小的数)

    输入输出格式

    输入格式:

    第一行为 (n) ,表示操作的个数,下面 (n) 行每行有两个数 (opt)(x)(opt) 表示操作的序号( (1 leq opt leq 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)

    1.(n) 的数据范围: (n leq 100000)

    2.每个数的数据范围: ([-{10}^7, {10}^7])


    题解

    PS:本题解就是给yyb巨佬的讲解贴个代码的

    推荐一发yyb巨佬的博客Splay入门解析

    本来是2月份学的东西。已经忘得差不多了。之前打的是treap,现在不会啦。
    那就打打模板吧。
    对于这六个操作。就第三个说一下吧。
    先找到这个值的节点。splay到根。那么它的排名就是它的左子树+1。
    特别注意我们要先加虚点(-inf)(inf)
    因为刚刚加点又删点时,查前驱和后继会卡死循环。

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int N=1e6+5;
    struct node{
        int ch[2],size;
        int ff,cnt,val;
    }t[N];
    int n,m,root=0,tot;
    int read(){
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    
    void pushup(int x){
        t[x].size=t[t[x].ch[1]].size+t[t[x].ch[0]].size+t[x].cnt;
    }
    
    void rotate(int x){
        int y=t[x].ff,z=t[y].ff,k=t[y].ch[1]==x;
        t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
        t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
        t[y].ff=x;t[x].ch[k^1]=y;
        pushup(y);pushup(x);
    }
    
    void splay(int x,int rt){
        while(t[x].ff!=rt){
            int y=t[x].ff,z=t[y].ff;
            if(z!=rt)
            (t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);rotate(x);
        }
        if(rt==0)root=x;
    }
    
    void find(int x){
        int u=root;if(!u)return ;
        while(t[u].ch[t[u].val<x]&&x!=t[u].val)
        u=t[u].ch[t[u].val<x];splay(u,0);
    }
    
    void insert(int x){
        int u=root,ff=0;
        while(u&&x!=t[u].val)
        ff=u,u=t[u].ch[t[u].val<x];
        if(u)t[u].cnt++;
        else{
            u=++tot;
            if(ff)t[ff].ch[t[ff].val<x]=u;
            t[tot].ff=ff;t[tot].val=x;
            t[tot].cnt=1;t[tot].size=1;
        }splay(u,0);
    }
    
    int Next(int x,int f){
        find(x);int u=root;
    //	cout<<x<<' '<<u<<' '<<f<<endl;
        if(t[u].val>x&&f)return u;
        if(t[u].val<x&&!f)return u;
        u=t[u].ch[f];
        while(t[u].ch[f^1])u=t[u].ch[f^1];
        return u;
    }
    
    void delet(int x){
        int pre=Next(x,0),nex=Next(x,1);
        splay(pre,0);splay(nex,pre);
        int u=t[nex].ch[0];
        if(t[u].cnt>1)t[u].cnt--,splay(u,0);
        else t[nex].ch[0]=0;
    }
    
    int kth(int x){
        int u=root;
        if(t[u].size<x)return 0;
        while(233){
            int y=t[u].ch[0];
            if(x>t[y].size+t[u].cnt){
                x-=t[y].size+t[u].cnt;
                u=t[u].ch[1];
            }
            else {
                if(t[y].size>=x)u=y;
                else return t[u].val;
            }
        }
    }
    
    int main(){
        m=read();insert(-1e9);insert(1e9);
        while(m--){
            int opt=read();
            if(opt==1){int x=read();insert(x);}
            if(opt==2){int x=read();delet(x);}
            if(opt==3){int x=read();find(x);printf("%d
    ",t[t[root].ch[0]].size);}
            if(opt==4){int x=read();x++;printf("%d
    ",kth(x));}
            if(opt==5){int x=read();printf("%d
    ",t[Next(x,0)].val);}
            if(opt==6){int x=read();printf("%d
    ",t[Next(x,1)].val);}
        }
        return 0;
    }
    
  • 相关阅读:
    C#第十六节课
    Hadoop系列(三):hadoop基本测试
    Hadoop系列(二):Hadoop单节点部署
    Hadoop系列(一):Hadoop集群搭建
    Stars project
    Tornado实现多进程/多线程的HTTP服务
    python paramiko模块
    爬虫代理
    tornado之用户验证装饰器
    tornado自定义session
  • 原文地址:https://www.cnblogs.com/hhh1109/p/9721203.html
Copyright © 2011-2022 走看看