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) );

            }

        }    

    }    

}

你可能感兴趣的:(树状数组)