zoukankan      html  css  js  c++  java
  • luoguP3369 【模板】普通平衡树(Splay)

    www.cnblogs.com/shaokele/


    luoguP3369 【模板】普通平衡树##

      Time Limit: 1 Sec
      Memory Limit: 128 MB

    Description###

      您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
      1.插入 (x)
      2.删除 (x) 数(若有多个相同的数,因只删除一个)
      3.查询 (x) 数的排名(排名定义为比当前数小的数的个数 (+1) 。若有多个相同的数,因输出最小的排名)
      4.查询排名为 (x) 的数
      5.求 (x) 的前驱(前驱定义为小于 (x) ,且最大的数)
      6.求 (x) 的后继(后继定义为大于 (x) ,且最小的数)
     

    Input###

      第一行为 (n) ,表示操作的个数,下面 (n) 行每行有两个数 (opt)(x)(opt) 表示操作的序号( (1 leq opt leq 6) )
     

    Output###

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

    Sample Input###

      10
      1 106465
      4 1
      1 317721
      1 460929
      1 644985
      1 84185
      1 89851
      6 81968
      1 492737
      5 493598
     

    Sample Output###

      106465
      84185
      492737
        

    HINT

      1.n的数据范围: $n leq 100000 $
      2.每个数的数据范围: ([-{10}^7, {10}^7])
      来源:Tyvj1728 原名:普通平衡树
      在此鸣谢
      

    题目地址:  luoguP3369 【模板】普通平衡树

    题目大意:   已经很简洁了

      

    题解:

      整理ing
      
      直接Splay
      
      参考


    AC代码

    #include <cstdio>
    using namespace std;
    const int N=1e5+5;
    int Q,op,x,root,size;
    int f[N],key[N],cnt[N],sz[N],T[N][2];
    inline void clear(int x){
    	T[x][0]=T[x][1]=f[x]=key[x]=cnt[x]=sz[x]=0;
    }
    inline int get(int x){						//判断当前节点是他父节点的左儿子还是右儿子 
    	return T[f[x]][1]==x;
    }
    inline void update(int x){
    	if(!x)return;
    	sz[x]=cnt[x];
    	if(T[x][0])sz[x]+=sz[T[x][0]];
    	if(T[x][1])sz[x]+=sz[T[x][1]];
    }
    inline void rotate(int x){					//x换上去 
    	int old=f[x],older=f[old],which=get(x);
    	T[old][which]=T[x][which^1];f[T[x][which^1]]=old;
    	T[x][which^1]=old;f[old]=x;
    	f[x]=older;
    	if(older)T[older][T[older][1]==old]=x;
    	update(old);update(x);
    }
    inline void splay(int x){					//rotate到根 
    	for(int fa;(fa=f[x]);rotate(x))
    		if(f[fa])rotate(get(fa)==get(x)?fa:x);
    	root=x;
    }
    inline void insert(int x){
        if(!root){
            root=++size;
            T[root][0]=T[root][1]=f[root]=0;
            key[root]=x;cnt[root]=1;
            return;
        }
        int now=root,fa=0;
        while(1){
            if(key[now]==x){
                cnt[now]++;
                update(now);update(fa);
                splay(now);
                return;
            }
            fa=now;now=T[now][x>key[now]];
            if(now==0){
                size++;
                T[size][0]=T[size][1]=0;
    			sz[size]=cnt[size]=1;key[size]=x;
                f[size]=fa;T[fa][x>key[fa]]=size;
                update(fa);
                splay(size);
                return;
            }
        }
    }
    inline int find(int x){   					//x的排名 
        int res=1,now=root;
        while(1){
            if(x<key[now])now=T[now][0];
            else{
                res+=(T[now][0]?sz[T[now][0]]:0);
                if(x==key[now]){
    				splay(now);
    				return res;
    			}
                res+=cnt[now]; 
                now=T[now][1];
            }
        }
    }
    inline int findx(int x){					//找到排名为x的点 
        int now=root;
        while(1){
            if(T[now][0] && x<=sz[T[now][0]])now=T[now][0];
            else{
                int tmp=(T[now][0]?sz[T[now][0]]:0)+cnt[now];
                if(x<=tmp)return key[now];
                x-=tmp;now=T[now][1];
            }
        }
    }
    inline int pre(){							//x的前驱 
        int now=T[root][0];
        while(T[now][1])now=T[now][1];
        return now;
    }
    inline int next(){							//x的后继 
        int now=T[root][1];
        while(T[now][0])now=T[now][0];
        return now;
    }
    inline void del(int x){
        find(x);								//将x旋到根 
        if(cnt[root]>1){cnt[root]--;return;} 	//不止有一个x的话,返回-1 
        //only one point
        if(!T[root][0] && !T[root][1]){clear(root);root=0;return;}
        //no left child
        if(!T[root][0]){
    		int old=root;
    		root=T[root][1];
    		clear(old);f[root]=0;
    		return;
    	} 
        //no right child 
        if(!T[root][1]){
    		int old=root;
    		root=T[root][0];
    		clear(old);f[root]=0;
    		return;
    	} 
        //two children 
        int left=pre(),old=root;
        splay(left);
        f[T[old][1]]=root;
        T[root][1]=T[old][1];
        clear(old);
        update(root); 
    }
    int main(){
    	scanf("%d",&Q);
    	while(Q--){
    		scanf("%d%d",&op,&x);
    		if(op==1)insert(x);
    		if(op==2)del(x);
    		if(op==3)printf("%d
    ",find(x));
    		if(op==4)printf("%d
    ",findx(x));
    		if(op==5)insert(x),printf("%d
    ",key[pre()]),del(x);
    		if(op==6)insert(x),printf("%d
    ",key[next()]),del(x);
    	}
    	return 0;
    }
    


      作者:skl_win
      出处:https://www.cnblogs.com/shaokele/
      本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    POJ 1753
    POJ 3669
    POJ 1979
    HDU 1372
    Codeforces 761D
    response下载csv文件内容乱码问题
    只要没有给String[]数组new 空间,那么他就只是一个引用
    servlet中的“/”代表当前项目,html中的“/”代表当前服务器
    onkeyup的死循环问题
    OPGL+VS2017+GLFW+GLEW配置详细步骤
  • 原文地址:https://www.cnblogs.com/shaokele/p/9463409.html
Copyright © 2011-2022 走看看