hdu-2852 KiKi's K-Number---二分+树状数组
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2852
题目大意:
题意:
给出三种操作,
0 在容器中插入一个数。
1 在容器中删除一个数。
2 求出容器中大于a的第k大元素。
解题思路:
用树状数组维护每个值,插入数字是add(x, 1),删除时add(x, -1)
查询第k大时,先判断是否存在,存在的话直接根据树状数组sum值的单调性二分法求解即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<map> 6 #include<set> 7 #include<cmath> 8 #include<algorithm> 9 #include<vector> 10 #include<sstream> 11 #define lowbot(i) (i&(-i)) 12 using namespace std; 13 typedef long long ll; 14 const int maxn = 1e5 + 10; 15 int tree[maxn]; 16 void add(int x, int d) 17 { 18 while(x <= 100000) 19 tree[x] += d, x += lowbot(x); 20 } 21 int sum(int x) 22 { 23 int ans = 0; 24 while(x)ans += tree[x], x -= lowbot(x); 25 return ans; 26 } 27 int Find(int x, int k) 28 { 29 int l = x + 1, r = 100000; 30 int mid, t; 31 while(l < r) 32 { 33 //cout<<l<<" "<<r<<endl; 34 mid = (l + r) / 2; 35 t = sum(mid) - sum(x); 36 if(t >= k) 37 r = mid; 38 else l = mid + 1; 39 } 40 return r; 41 } 42 int main() 43 { 44 int n, x, k; 45 while(scanf("%d", &n) != EOF) 46 { 47 memset(tree, 0, sizeof(tree)); 48 while(n--) 49 { 50 scanf("%d", &x); 51 if(x == 0) 52 { 53 scanf("%d", &x); 54 add(x, 1); 55 } 56 else if(x == 1) 57 { 58 scanf("%d", &x); 59 if(sum(x) == sum(x - 1)) 60 printf("No Elment!\n"); 61 else add(x, -1); 62 } 63 else if(x == 2) 64 { 65 scanf("%d%d", &x, &k); 66 if(sum(100000) - sum(x) < k) 67 printf("Not Find!\n"); 68 else 69 { 70 printf("%d\n", Find(x, k)); 71 } 72 } 73 } 74 } 75 return 0; 76 }
越努力,越幸运