首页 > 代码库 > HDU 2852 KiKi's K-Number (树状数组 && 二分)

HDU 2852 KiKi's K-Number (树状数组 && 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作。这里对于一个容器提供三种操作, 分别是插入、删除和查找。输入0  e表示插入e、输入1  e表示删除e,若元素不存在输出No Elment!、输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find!

 

分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有多少个(tot代表集合里面元素的总数)。如果大于或等于 k 则存在比这个数大且是第k大的数, 接下来只要二分查找即可!

 

瞎搞:当时没有想到二分, 而是直接丢进一个multiset中, 让后进行迭代查找操作, 别说了, TEL得好惨……

 

技术分享
#include<bits/stdc++.h>
#define lowbit(i) (i&(-i))
using namespace std;
const int maxn = 1e5+1;
int c[maxn];
inline void add(int i, int val)
{
    while(i<=100000){
        c[i] += val;
        i += lowbit(i);
    }
}
int sum(int i)
{
    int ans = 0;
    while(i>0){
        ans += c[i];
        i -= lowbit(i);
    }
    return ans;
}
int vis[maxn];
int Bin_search(int L, int R, int key, int index)
{
    int mid;
    while(L < R){
        mid = L + ((R-L)>>1);
        if(sum(mid) - sum(index)  < key) L = mid + 1;
        else R = mid;
    }
    return R;
}
int main(void)
{
    int n;
    while(~scanf("%d", &n) && n){
        memset(c, 0, sizeof(c));
        memset(vis, 0, sizeof(vis));
        int command;
        int tot = 0;
        int M = 0;
        for(int t=1; t<=n; t++){
            scanf("%d", &command);
            if(command==0){
                int temp;
                scanf("%d", &temp);
                if(temp>M) M = temp;
                vis[temp]++;
                add(temp, 1);
                tot++;
            }
            else if(command==1){
                int temp;
                scanf("%d", &temp);
                if(vis[temp]){
                    tot--;
                    add(temp, -1);
                    vis[temp]--;
                }else{
                    puts("No Elment!");
                }
            }
            else{
                int a, b;
                int ans;
                scanf("%d%d", &a, &b);
                if(tot-sum(a) >= b){
                    int ans = Bin_search(a, M, b, a);
                    printf("%d\n", ans);
                }else{
                    puts("Not Find!");
                }
            }
        }
    }
    return 0;
}
View Code

 

HDU 2852 KiKi's K-Number (树状数组 && 二分)