HDU 2852 KiKi's K-Number (樹狀數組 && 二分)
阿新 • • 發佈:2017-05-29
eof while ron name += oid names 如果 一個
題意:給出對容器的總操作次數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(intView Codei) { 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; }
HDU 2852 KiKi's K-Number (樹狀數組 && 二分)