hdu 2852 KiKi's K-Number (线段树)
版权声明:本文为博主原创文章,未经博主允许不得转载。
题意:
一个容器,三种操作:
(1) 加入一个数 e
(2) 删除一个数 e,如果不存在则输出 No Elment!
(3) 查询比a大的数中的第k小数,不存在就输出 Not Find!
解法:
关于第三点,可以先查询小于等于a的数的个数cnt,然后直接查询第cnt+k小数就行了 。
二分+树状数组 或者 主席树(有点杀鸡用牛刀的感觉 。。。) 也是可以做的 _(:з」∠)_
code:线段树
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <cstring> 6 #include <queue> 7 #include <set> 8 #include <vector> 9 #include <map> 10 #define ll long long 11 12 using namespace std; 13 14 const int N=1e5+7; 15 16 int L[N*4],R[N*4],cnt[N*4]; 17 18 inline void bulidtree(int l,int r,int k){ 19 L[k]=l; R[k]=r; 20 cnt[k]=0; 21 if (l==r) return; 22 int mid=(l+r)>>1; 23 bulidtree(l,mid,k<<1); 24 bulidtree(mid+1,r,(k<<1)|1); 25 } 26 27 inline void update(int p,int d,int k){ 28 cnt[k]+=d; 29 if (L[k]==R[k]) return; 30 int mid=(L[k]+R[k])>>1; 31 if (p<=mid) update(p,d,k<<1); 32 else update(p,d,(k<<1)|1); 33 } 34 35 inline int query(int x,int y,int k){ 36 if (L[k]==x && R[k]==y) 37 return cnt[k]; 38 int mid=(L[k]+R[k])>>1; 39 if (y<=mid) return query(x,y,k<<1); 40 else if (x>mid) return query(x,y,(k<<1)|1); 41 else return query(x,mid,k<<1)+query(mid+1,y,(k<<1)|1); 42 } 43 44 inline int find(int x,int k){ 45 if (cnt[k]<x) return -1; 46 while (L[k]!=R[k]){ 47 if (x<=cnt[k<<1]) k=k<<1; 48 else { 49 x-=cnt[k<<1]; 50 k=(k<<1)|1; 51 } 52 } 53 return L[k]; 54 } 55 56 int main(){ 57 int m; 58 while (~scanf("%d",&m)){ 59 int p,x,y; 60 bulidtree(1,N-7,1); 61 while (m--){ 62 scanf("%d",&p); 63 switch(p){ 64 case 0: 65 scanf("%d",&x); 66 update(x,1,1); 67 break; 68 case 1: 69 scanf("%d",&x); 70 if (query(x,x,1)) update(x,-1,1); 71 else puts("No Elment!"); 72 break; 73 case 2: 74 scanf("%d%d",&x,&y); 75 int ans=find(query(1,x,1)+y,1); 76 if (~ans) printf("%d\n",ans); 77 else puts("Not Find!"); 78 break; 79 } 80 } 81 } 82 return 0; 83 }