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/
  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/shaokele/p/9463409.html