写一棵平衡树,要求实现以下操作,插入、删除数字,查询某个数字是第几大的,查询第k大的数字是几。
因为懒得写删除节点的操作...于是直接当作multiset写了..
#include <cstdio>
#include <cstdlib>
#include <ctime>
const int MAXINT=~0u>>1;
struct TreapNode {
TreapNode *ls,*rs,*f;
int x,num,size,ran;
TreapNode *clear(int xx,TreapNode *ff=NULL) {
f=ff;
x=xx;
ls=rs=NULL;
num=size=1;
ran=rand();
return this;
}
void repairSize() {
size=num;
if (ls) size+=ls->size;
if (rs) size+=rs->size;
}
void rot() {
TreapNode *x=this,*y=this->f;
if (x==y->ls) {
y->ls=x->rs;
x->rs=y;
if (y->ls) y->ls->f=y;
} else {
y->rs=x->ls;
x->ls=y;
if (y->rs) y->rs->f=y;
}
x->f=y->f;
y->f=x;
if (x->f)
if (x->f->ls==y) x->f->ls=x;
else x->f->rs=x;
y->repairSize();
x->repairSize();
}
};
TreapNode b[200010],*bp,*root;
void print() {
printf("Root: %d\n",(int)(root-b));
for (TreapNode *cur=b;cur!=bp;cur++) {
printf("Node %d:\n",(int)(cur-b));
printf(" ls:%d rs:%d f:%d\n",(int)(cur->ls-b),(int)(cur->rs-b),(int)(cur->f-b));
printf(" x:%d num:%d size:%d ran:%d\n",cur->x,cur->num,cur->size,cur->ran);
}
printf("\n");
}
void upRepair(TreapNode *x) {
while (x->f&&x->ran<x->f->ran) x->rot();
if (x->f==NULL) root=x;
}
bool has(int x) {
for (TreapNode *cur=root;cur;) {
if (cur->x==x) {
if (cur->num>0) return true;
else return false;
} else if (x<cur->x) cur=cur->ls;
else cur=cur->rs;
}
return false;
}
void insert(int x) {
if (has(x)) return;
for (TreapNode *cur=root;cur;) {
cur->size++;
if (x<cur->x) {
if (cur->ls) cur=cur->ls;
else {
cur->ls=(bp++)->clear(x,cur);
upRepair(cur->ls);
return;
}
} else {
if (cur->rs) cur=cur->rs;
else {
cur->rs=(bp++)->clear(x,cur);
upRepair(cur->rs);
return;
}
}
}
}
bool erase(int x) {
if (!has(x)) return false;
for (TreapNode *cur=root;cur;) {
cur->size--;
if (cur->x==x) {
cur->num--;
return true;
} else if (x<cur->x) cur=cur->ls;
else cur=cur->rs;
}
}
int kth(int k) {
for (TreapNode *cur=root;cur;) {
if (cur->ls) {
if (k<=cur->ls->size) {
cur=cur->ls;
continue;
} else k-=cur->ls->size;
}
if (k<=cur->num) {
return cur->x;
} else k-=cur->num;
cur=cur->rs;
}
return MAXINT;
}
int count(int x) {
int ans=0;
for (TreapNode *cur=root;cur;) {
if (x==cur->x) {
if (cur->ls) ans+=cur->ls->size;
return ans;
} else if (x>cur->x) {
if (cur->ls) ans+=cur->ls->size;
ans+=cur->num;
cur=cur->rs;
} else cur=cur->ls;
}
return ans;
}
void clear() {
bp=b;
root=(bp++)->clear(MAXINT);
}
int main() {
srand(time(0));
int q,x;
char c;
scanf("%d",&q);
clear();
while (q--) {
scanf(" %c%d",&c,&x);
if (c=='I') insert(x);
else if (c=='D') erase(x);
else if (c=='K') {
int ans=kth(x);
if (ans==MAXINT) printf("invalid\n");
else printf("%d\n",ans);
} else {
printf("%d\n",count(x));
}
//print();
}
return 0;
}