HDU-Yuna's confusion 树状数组 Or Multiset

比赛的时候竟然没有想到这题可以用树状数组过,由于数字的区间比较小,所以直接开设一个树状数组,定义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) );
            }
        }    
    }    
}
posted @ 2012-08-12 20:28  沐阳  阅读(299)  评论(0编辑  收藏  举报