3224: Tyvj 1728 普通平衡树

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]
 
模板题
  1 #include<cstdio>
  2 #include<cstdlib>
  3 using namespace std;
  4 struct tree{
  5     int l,r,sum,s,num,rnd;
  6 }tr[1000001];
  7 int cnt,t1,t2,n,opt,x,root; 
  8 void updata(int k){
  9     int l=tr[k].l,r=tr[k].r;
 10     tr[k].s=tr[l].s+tr[r].s+tr[k].sum;
 11 }
 12 
 13 void lturn(int &k){
 14     int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k;
 15     tr[t].s=tr[k].s;updata(k);k=t;
 16 }
 17 
 18 void rturn(int &k){
 19     int t=tr[k].l; tr[k].l=tr[t].r;tr[t].r=k;
 20     tr[t].s=tr[k].s;updata(k);k=t;
 21 }
 22 
 23 void insert(int &k,int x){
 24 if (!k){
 25         cnt++;k=cnt;tr[k].num=x; tr[k].s=1; tr[k].rnd=rand();tr[k].sum++;return;
 26     }
 27     tr[k].s++;
 28     if (x<tr[k].num){
 29         insert(tr[k].l,x);
 30         if (tr[tr[k].l].rnd<tr[k].rnd) rturn(k);
 31     }
 32     else if (x>tr[k].num){
 33         insert(tr[k].r,x);
 34         if (tr[tr[k].r].rnd<tr[k].rnd) lturn(k);
 35     }
 36     else if (x==tr[k].num) {
 37         tr[k].sum++;
 38         return; 
 39     }
 40 }
 41 
 42 void del(int &k,int x){
 43     if (k==0) return;
 44     if (tr[k].num==x){
 45         if (tr[k].sum>1){
 46             tr[k].sum--;tr[k].s--; return;
 47         }
 48         if (tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r;
 49         else if (tr[tr[k].l].rnd<tr[tr[k].r].rnd) 
 50             rturn(k),del(k,x);
 51             else lturn(k),del(k,x);
 52     }
 53     else if (x>tr[k].num) tr[k].s--,del(tr[k].r,x);
 54     else tr[k].s--,del(tr[k].l,x);
 55 }
 56 
 57 int find1(int &k,int x){
 58     if (k==0) return 0;
 59     if (tr[k].num==x) return tr[tr[k].l].s+1;
 60     if (tr[k].num>x) return find1(tr[k].l,x);
 61     if (tr[k].num<x) return tr[tr[k].l].s+tr[k].sum+find1(tr[k].r,x);
 62 } 
 63 
 64 int find2(int &k,int x){
 65     if (k==0) return 0;
 66     int l=tr[k].l,r=tr[k].r;
 67     if (tr[l].s+1<=x&&tr[l].s+tr[k].sum>=x) return tr[k].num;
 68     if (tr[l].s>=x) return find2(l,x);
 69     if (tr[l].s+tr[k].sum<x) return find2(r,x-tr[l].s-tr[k].sum);
 70 }
 71 
 72 void pre(int &k,int x){
 73     if (k==0) return;
 74     if (tr[k].num<x){
 75         t1=k;
 76         pre(tr[k].r,x);
 77     }
 78     else pre(tr[k].l,x);
 79 }
 80 
 81 void after(int &k,int x){
 82     if (k==0) return;
 83     if (tr[k].num>x){
 84         t2=k;
 85         after(tr[k].l,x);
 86     }
 87     else after(tr[k].r,x);
 88 }
 89 
 90 int main(){
 91     scanf("%d",&n);
 92     while (n--){
 93         scanf("%d%d",&opt,&x);
 94         t1=t2=0;
 95         switch(opt){
 96             case 1:insert(root,x); break;
 97             case 2:del(root,x); break;
 98             case 3:printf("%d\n",find1(root,x)); break;//查询x数的排名 
 99             case 4:printf("%d\n",find2(root,x));break;
100             case 5:pre(root,x);printf("%d\n",tr[t1].num);break;
101             case 6:after(root,x);printf("%d\n",tr[t2].num);break;
102         }
103 
104     }
105 }

 

posted @ 2016-01-15 11:24  Alisahhh  阅读(145)  评论(0编辑  收藏  举报