[BZOJ 3224]普通平衡树
很好,这很interesting。
最大坑点是数可能重复。然后前驱后驱赶脚也挺坑的……
还有好像BZOJ不滋磁time(0)哎。所以我就用了wyy的生日做随机数种子辣!
代码:
/**************************************************************
Problem: 3224
User: danihao123
Language: C++
Result: Accepted
Time:376 ms
Memory:1880 kb
****************************************************************/
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct Node{
Node *ch[2];
int v;
int r;
int s;
int cnt;
Node(){
v=s=cnt=0;
r=-1;
ch[0]=ch[1]=NULL;
}
Node(int key,Node *lc,Node *rc){
v=key;
r=rand();
s=1;
cnt=1;
ch[0]=lc;
ch[1]=rc;
}
void maintain(){
s=ch[0]->s+ch[1]->s+cnt;
}
};
struct Treap{
Node *null,*root;
Treap(){
null=new Node();
root=null;
}
void rotate(Node* &o,int d){
Node* k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
o->maintain();
k->maintain();
o=k;
}
void insert(Node* &o,int x){
if(o==null){
o=new Node(x,null,null);
}else{
if(o->v==x){
o->cnt++;
o->s++;
}else{
int d=x>(o->v);
insert(o->ch[d],x);
if(((o->ch[d])->r)>(o->r))
rotate(o,d^1);
}
}
o->maintain();
}
void del(Node* &o,int x){
if(o->v==x){
if(o->cnt>1){
o->cnt--;
o->s--;
}else{
if(o->ch[0]==null){
Node *u=o;
o=o->ch[1];
delete u;
}else{
if(o->ch[1]==null){
Node *u=o;
o=o->ch[0];
delete u;
}else{
int d=(o->ch[1]->r)>(o->ch[0]->r);
rotate(o,d^1);
del(o->ch[d^1],x);
}
}
}
}else{
int d=x>(o->v);
del(o->ch[d],x);
}
if(o!=null)
o->maintain();
}
int kth(Node *o,int k){
if(k<=(o->ch[0]->s)){
return kth(o->ch[0],k);
}else{
k-=o->ch[0]->s;
if(k<=o->cnt)
return o->v;
else
return kth(o->ch[1],k-(o->cnt));
}
}
int rank(Node *o,int x){
if(o==null)
return 0;
if(x<(o->v)){
return rank(o->ch[0],x);
}else{
if(x==o->v)
return o->ch[0]->s+1;
else
return o->ch[0]->s+o->cnt+rank(o->ch[1],x);
}
}
int pre(int x){
Node *cur=root;
int ans=0;
while(cur!=null){
if(cur->v<x){
ans=cur->v;
cur=cur->ch[1];
}else{
cur=cur->ch[0];
}
}
return ans;
}
int suc(int x){
Node *cur=root;
int ans=0;
while(cur!=null){
if(cur->v>x){
ans=cur->v;
cur=cur->ch[0];
}else{
cur=cur->ch[1];
}
}
return ans;
}
};
int main(){
int n;
int opt,x;
Treap T;
scanf("%d",&n);
srand(20020601);
while(n--){
scanf("%d%d",&opt,&x);
if(opt==1){
T.insert(T.root,x);
}else{
if(opt==2){
T.del(T.root,x);
}else{
if(opt==3){
printf("%d\n",T.rank(T.root,x));
}else{
if(opt==4){
printf("%d\n",T.kth(T.root,x));
}else{
if(opt==5){
printf("%d\n",T.pre(x));
}else{
printf("%d\n",T.suc(x));
}
}
}
}
}
}
return 0;
}