權值樹狀數組 HDU-2852 KiKi's K-Number

引入

權值樹狀數組就是數組下標是數值的數組,數組存儲下標對應的值有幾個數數組

題目 HDU-2852 KiKi's K-Number

題意

幾種操做,p=0表明push:將數值爲a的數壓入盒子spa

p=1表明pop,表明刪除數值爲e的數,若是沒有這個數,輸出No Elment!code

p=2表明query,查詢比第k個比a大的元素,找不到輸出Not Find!input

Sample Input

5
0 5
1 2
0 6
2 3 2
2 8 1
7
0 2
0 2
0 4
2 1 1
2 1 2
2 1 3
2 1 4

Sample Output

No Elment!
6
Not Find!
2
2
4
Not Find!

題解

此題正是權值樹狀數組的應用,插入和刪除都比較簡單再也不贅述了,重點是查詢怎麼查詢,咱們的樹狀數組是存儲的對應權值的個數。咱們在查詢的時候,首先查詢出a是第\(x\)大的元素,那麼查詢比a大k的元素就轉化爲查詢第\(x+k\)大的元素,而後咱們二分查找,判斷當前的數是第幾大的數,多了就向小二分,但要注意判斷,若是當前找到的是第\(res\)大的數,vis[mid]表明這個數有多少個,若是\(res-vis[mid] < k 且res >= k\)說明mid就是要找的數string

AC代碼

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100005
using namespace std;
typedef long long ll;
int lowbit(int x) {
    return x & (-x);
}
int min(int a, int b) {return a < b ? a : b; }
int max(int a, int b) {return a > b ? a : b; }
int m;
int d[N + 5];
void update(int x, int val) {
    for (; x <= N; x += lowbit(x))
        d[x] += val;
}
int query(int x) {
    int ans = 0;
    for (; x; x -= lowbit(x))
        ans += d[x];
    return ans;
}
int vis[N];
int main() {
    while (scanf("%d", &m) != EOF) {
        memset(d, 0, sizeof(d));
        memset(vis, 0, sizeof(vis));
        for (int i = 1; i <= m; i++) {
            int p, x;
            scanf("%d", &p);
            if (p == 0) {
                scanf("%d", &x);
                vis[x]++;
                update(x, 1);
            }
            else if (p == 1) {
                scanf("%d", &x);
                if (vis[x]) {
                    update(x, -1);
                    vis[x]--;
                }
                else printf("No Elment!\n");
            }
            else {
                int a, k;
                scanf("%d%d", &a, &k);
                int l = 1, r = N;
                int ans;
                if (query(r) - query(a) < k)
                    printf("Not Find!\n");
                else {
                    int x = query(a) + k;
                    while (l <= r) {
                        int mid = (l + r) >> 1;
                        int res = query(mid);
                        if (res >= x) {
                            if (vis[mid] == 0) r = mid - 1;
                            else if (res - vis[mid] < x) {
                                ans = mid;
                                break;
                            }
                            else r = mid - 1;
                        }
                        else l = mid + 1;
                    }
                    printf("%d\n", ans);
                }
            }
        }
    }
    return 0;
}
相關文章
相關標籤/搜索