比赛的时候竟然没有想到这题可以用树状数组过,由于数字的区间比较小,所以直接开设一个树状数组,定义sum(i) 表示小于i的数的总数。那么判定一个数是否有的条件就是计算sum(i+1) == sum(i) 便可以了,查找第K大的数,也就可以直接二分了。
代码如下:
#include <cstdlib> #include <cstring> #include <cstdio> #include <algorithm> #define MAXN 100000 using namespace std;int c[MAXN+5];int lowbit(int x) {return x & -x; }void modify(int x, int val) {for (int i = x; i <= MAXN; i += lowbit(i)) {c[i] += val;} }int sum(int x) {int ret = 0;for (int i = x; i > 0; i -= lowbit(i)) {ret += c[i];}return ret; }int bsearch(int l, int r, int k) {int mid, ret = -1;while (l <= r) {mid = (l + r) >> 1;// printf("mid = %d, sum() = %d\n", mid, sum(mid));// getchar();if (sum(mid) >= k) {ret = mid;r = mid - 1; }else {l = mid + 1; }}return ret; }int main() {int M, x, y, ret;char op[5];while (scanf("%d", &M) == 1) {memset(c, 0, sizeof (c));for (int i = 1; i <= M; ++i) {scanf("%s", op);if (op[0] == 'A') {scanf("%d", &x);modify(x, 1); }else if (op[0] == 'D'){scanf("%d", &x);// printf("%d %d\n", sum(x), sum(x-1));if (sum(x) == sum(x-1)) {puts("No Elment!");}else {modify(x, -1);}}else { // query通过二分查找来对付 scanf("%d %d", &x, &y);y += sum(x);ret = bsearch(x+1, MAXN, y);if (ret == -1) {puts("Not Find!");}else {printf("%d\n", ret);}}} }return 0; }
还有一种做法,就是直接用STL中的multiset.
代码如下:
#include<iostream> #include<algorithm> #include<set> using namespace std;multiset<int> s; multiset<int>::iterator it;int main(){int Q;while( ~scanf("%d",&Q)){s.clear();char ope[10];int x,k;for(int i = 1; i <= Q; i++){scanf("%s", ope);if( ope[0] == 'A' ){scanf("%d",&x);s.insert(x); }else if( ope[0] == 'D' ){scanf("%d",&x);int cnt = s.count(x);if( cnt == 0 ){puts("No Elment!");continue; }s.erase(x);for(int i = 1; i <= cnt-1; i++)s.insert(x); }else {scanf("%d%d",&x,&k);it = s.upper_bound(x);if( it == s.end() ){//|| (it+(k-1) >= s.end() ) ){puts("Not Find!");continue;} int i=1;for(; it != s.end() && i < k; i++, it++); if( it == s.end() ){puts("Not Find!");continue;}printf("%d\n", *(it) );}} } }