Bsoj 1322 第K小数

 

 

第K小数
Description
  现在已有N个整数,你有以下三种操作:
1 A:表示加入一个值为A的整数;
2 B:表示删除其中值为B的整数;
3 K:表示输出这些整数中第K小的数;
Input
第一行,两个整数N,M,表示最开始有N个整数,总共有M个操作
第二行用空格隔开的N个整数
接下来M行,每行表示一个操作
Output
若干行,一行一个整数,表示所求的第K小的数字
Sample Input
5 5
6 2 7 4 9
1 8
1 6
3 10
2 4
3 3
Sample Output
0
7
Hint
【注意】:如果有多个大小相同的数字,只把他们看做一个数字,如样例。 若找不到第K小的数,输出0
【数据范围】
0<=N<=2,000,000
M<=1,000,000
-1,000,000,000<=每个整数<=1,000,000,000

 

 

写个普通的treap就好

  1 /*by SilverN*/
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<algorithm>
  7 using namespace std;
  8 int n,m;
  9 struct treap{
 10     int l,r;//左右子树 
 11     int val,ct;//值 重复次数 
 12     int size,rand;//管控数量,随机权值 
 13 }t[120000];
 14 int root=0,cnt=0;
 15 int ans;
 16 void update(int k){
 17     t[k].size=t[t[k].l].size+t[t[k].r].size+t[k].ct;
 18 }
 19 void lt(int &k){//左旋 
 20     int now=t[k].r;
 21     t[k].r=t[now].l;
 22     t[now].l=k;
 23     t[now].size=t[k].size;
 24     update(k);
 25     k=now;
 26     return;
 27 }
 28 void rt(int &k){
 29     int now=t[k].l;
 30     t[k].l=t[now].r;
 31     t[now].r=k;
 32     t[now].size=t[k].size;
 33     update(k);
 34     k=now;
 35     return;
 36 }
 37 void insert(int &k,int x){
 38     if(k==0){
 39         t[++cnt].val=x;
 40         t[cnt].size=1;
 41         t[cnt].ct=1;
 42         t[cnt].rand=rand();
 43         k=cnt;
 44         return;
 45     } 
 46     t[k].size++;
 47     if(t[k].val==x) return;//多个重复数字看做一个 
 48     else if(x>t[k].val){
 49         insert(t[k].r,x);
 50         if(t[t[k].r].rand<t[k].rand) lt(k);
 51     }else{//x<t[k].val
 52         insert(t[k].l,x);
 53         if(t[t[k].l].rand<t[k].rand) rt(k);
 54     }
 55     return;
 56 }
 57 void del(int &k,int x){
 58     if(k==0)return;
 59     if(t[k].val==x){
 60         if(t[k].ct>1){t[k].ct--;t[k].size--;return;}
 61         if(t[k].l*t[k].r==0)k=t[k].l+t[k].r;//如果k是链结点(只有一个子节点),由其子节点补位 
 62         else{
 63             if(t[t[k].l].rand<t[t[k].r].rand){
 64                 rt(k);
 65                 del(k,x);
 66             }
 67             else{
 68                 lt(k);
 69                 del(k,x);
 70             }
 71         }
 72         return;
 73     }
 74     t[k].size--;
 75     if(x>t[k].val)del(t[k].r,x);
 76     if(x<t[k].val)del(t[k].l,x);
 77     return;
 78 }
 79 int ask_num(int k,int x){// 已知排名问数字 
 80     if(!k)return 0;
 81     if(x<=t[t[k].l].size)return ask_num(t[k].l,x);//排名小于左子树包含结点数量,则往左查 
 82     if(x>t[t[k].l].size+t[k].ct)return ask_num(t[k].r,x-t[t[k].l].size-t[k].ct);
 83     //排名大于“左子树结点数加父结点重复数”,则往右查 
 84     else return t[k].val;//否则返回父结点值 
 85 }
 86 int main(){
 87     int opt,x;
 88     scanf("%d%d",&n,&m);
 89     for(int i=1;i<=n;i++){
 90         scanf("%d",&x);
 91         insert(root,x);
 92     }
 93     while(m--){
 94         scanf("%d%d",&opt,&x);
 95         switch(opt){
 96             case 1:    insert(root,x);    break;
 97             case 2: del(root,x); break;                
 98             case 3: printf("%d\n",ask_num(root,x));break;
 99         }
100 //        for(int i=1;i<=cnt;i++)printf("%d ",t[i].val);
101 //        cout<<endl;
102     }
103     return 0;
104 }

 

posted @ 2016-06-07 23:36  SilverNebula  阅读(331)  评论(0编辑  收藏  举报
AmazingCounters.com