bzoj3224: Tyvj 1728 普通平衡树

treap模板。把ask_before和ask_after改成递归的形式会快很多。想把其他的操作也改成递归的形式。。。但是太麻烦了T_T

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cstdlib>
#include<ctime>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){
		if(c=='-') f=-1;c=getchar();
	}
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x*f;
}
const int nmax=1e5+5;
struct node{
	int l,r,v,sz,rd,w;
};node ns[nmax];
int n,rt,cnt=0;
void update(int x){
	ns[x].sz=ns[ns[x].l].sz+ns[ns[x].r].sz+ns[x].w;
}
void rturn(int &x){
	int t=ns[x].l;ns[x].l=ns[t].r;ns[t].r=x;
	ns[t].sz=ns[x].sz;update(x);x=t;
}
void lturn(int &x){
	int t=ns[x].r;ns[x].r=ns[t].l;ns[t].l=x;
	ns[t].sz=ns[x].sz;update(x);x=t;
}
void insert(int &k,int x){
	if(!k){
		cnt++;k=cnt;
		ns[k].sz=ns[k].w=1;ns[k].v=x;ns[k].rd=rand();
		return ;
	}
	ns[k].sz++;
	if(ns[k].v==x) ns[k].w++;
	else if(ns[k].v<x) {
		insert(ns[k].r,x);
		if(ns[ns[k].r].rd<ns[k].rd) lturn(k);
	}else{
		insert(ns[k].l,x);
		if(ns[ns[k].l].rd<ns[k].rd) rturn(k);
	}
}
void del(int &k,int x){
	if(!k) return ;
	if(ns[k].v==x){
		if(ns[k].w>1) ns[k].w--,ns[k].sz--;
		else{
			if(ns[k].l*ns[k].r==0) k=ns[k].l+ns[k].r;
			else if(ns[ns[k].l].rd<ns[ns[k].r].rd) rturn(k),del(k,x);
			else lturn(k),del(k,x);
		}
	}else if(x>ns[k].v) ns[k].sz--,del(ns[k].r,x);
	else ns[k].sz--,del(ns[k].l,x);
}
int ask_rank(int k,int x){
	if(!k) return 0;
	if(ns[k].v==x) return ns[ns[k].l].sz+1;
	else if(x>ns[k].v) return ns[ns[k].l].sz+ns[k].w+ask_rank(ns[k].r,x);
	else return ask_rank(ns[k].l,x);
}
int ask_num(int k,int x){
	if(!k) return 0;
	if(x<=ns[ns[k].l].sz) return ask_num(ns[k].l,x);
	else if(x>ns[ns[k].l].sz+ns[k].w) return ask_num(ns[k].r,x-ns[ns[k].l].sz-ns[k].w);
	else return ns[k].v;
}
int ask_before(int x){
	int t=rt,ans=0;
	while(t){
		if(ns[t].v<x) ans=ns[t].v,t=ns[t].r;
		else t=ns[t].l;
	}
	return ans;
}
int ask_after(int x){
	int t=rt,ans=0;
	while(t){
		if(ns[t].v>x) ans=ns[t].v,t=ns[t].l;
		else t=ns[t].r;
	}
	return ans;
}
int main(){
	srand(10000007);
	n=read();int u,v,d;
	rep(i,1,n){
		u=read(),v=read();
		if(u==1) insert(rt,v);
		else if(u==2) del(rt,v);
		else if(u==3) printf("%d\n",ask_rank(rt,v));
		else if(u==4) printf("%d\n",ask_num(rt,v));
		else if(u==5) printf("%d\n",ask_before(v));
		else printf("%d\n",ask_after(v));
	}
	return 0;
}
/*
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
*/

  

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 8619  Solved: 3651
[Submit][Status][Discuss]

Description

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

Input

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

2.每个数的数据范围:[-1e7,1e7]

数据如下http://pan.baidu.com/s/1jHMJwO2

 

Source

posted @ 2016-09-23 13:33  BBChq  阅读(152)  评论(0编辑  收藏  举报