[luogu3369] 普通平衡树(splay模板)

题目描述

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

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

输入输出格式

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

输出格式:
对于操作 3,4,5,63,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

说明

code:

//By Menteur_Hxy
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define M(a,b) memset(a,(b),sizeof(a))
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
#define C(i,a,b) for(register int i=(b);i>=(a);i--)
#define E(i,u) for(register int i=head[u];i;i=nex[i])
using namespace std;

inline LL rd() {
	LL x=0,fla=1; char c=' ';
	while(c>'9'|| c<'0') {if(c=='-') fla=-fla; c=getchar();}
	while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
	return x*fla;
}

inline void out(LL x){
    int a[25],wei=0;
    if(x<0) putchar('-'),x=-x;
    for(;x;x/=10) a[++wei]=x%10;
    if(wei==0){ puts("0"); return;}
    for(int j=wei;j>=1;--j) putchar('0'+a[j]);
    putchar('\n');
}
/*--splay_begin--*/ 
#define check(x) (x==nd[fa[x]][1])
#define clear(x) key[x]=cnt[x]=siz[x]=fa[x]=nd[x][1]=nd[x][0]=0
#define update(x) siz[x]=siz[nd[x][1]]+siz[nd[x][0]]+cnt[x]
const int N=100005;
int key[N],cnt[N],siz[N],fa[N],nd[N][2];
int size,root;

inline int newnode(int x) {key[++size]=x,cnt[size]=siz[size]=1;return size;}
inline void rotate(int x) { int old=fa[x],oldf=fa[old];
	bool wh=check(x);
	fa[nd[x][wh^1]]=old; nd[old][wh]=nd[x][wh^1];
	nd[x][wh^1]=old; fa[old]=x; fa[x]=oldf;
	if(oldf) nd[oldf][nd[oldf][1]==old]=x;
	update(old);update(x);
}
inline void splay(int x) {
	for(int f=fa[x];f;rotate(x),f=fa[x])
		if(fa[f]) rotate(check(f)==check(x)?f:x);
	root=x;
}
inline void insert(int x) {
	if(!root) {root=newnode(x);return ;}
	int now=root,f=0;
	while(1) {
		if(key[now]==x) {cnt[now]++;update(now);update(f);splay(now);return ;}
		f=now,now=nd[now][x>key[now]];
		if(!now) {now=newnode(x);fa[now]=f;nd[f][x>key[f]]=now;update(f);splay(now);return ;}
	}
}
inline int rk(int x) { int now=root,ans=0;
	while(1) {
		if(x<key[now]) now=nd[now][0];
		else {
			ans+=siz[nd[now][0]];
			if(key[now]==x) return splay(now),ans+1;
			ans+=cnt[now]; now=nd[now][1];
		}
	}
}
inline int kth(int x) { int now=root;
	while(1) {
		if(nd[now][0]&&x<=siz[nd[now][0]]) now=nd[now][0];
		else {
			x-=siz[nd[now][0]]+cnt[now];
			if(x<=0) return now;
			now=nd[now][1];
		}
	}
}
inline int prenxt(int now) { int wh=check(now);
	while(nd[now][wh^1]) now=nd[now][wh^1];
	return now;
}
inline void del(int x) {
	rk(x);
	if(cnt[root]>1) {cnt[root]--;update(root);return ;}
	if(!nd[root][0]&&!nd[root][1]) {clear(root);root=0;return ;}
	if(!nd[root][0]) {int old=root;root=nd[root][1];fa[root]=0;clear(old);return ;}
	if(!nd[root][1]) {int old=root;root=nd[root][0];fa[root]=0;clear(old);return ;}
	int old=root;
	splay(prenxt(nd[root][0]));
	nd[root][1]=nd[old][1];
	fa[nd[old][1]]=root;
	clear(old);
	update(root);
	return ; 
}
/*--splay_end--*/
int main() {
    int n=rd();
    for(int i=1;i<=n;i++) { int opt=rd(),x=rd();
        switch(opt) { 
            case 1:insert(x);break;
            case 2:del(x);break;
            case 3:out(rk(x));break;
            case 4:out(key[kth(x)]);break;
            case 5:insert(x);out(key[prenxt(nd[root][0])]);del(x);break;
            case 6:insert(x);out(key[prenxt(nd[root][1])]);del(x);break;   
        }
    }
    return 0;
}
posted @ 2018-06-14 17:29  Menteur_hxy  阅读(222)  评论(0编辑  收藏  举报