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 }
本文为博主原创文章,转载请注明出处。