HDU 4417 (二分 + 区间第k大)

来源:互联网 发布:优化教育环境 编辑:程序博客网 时间:2024/06/05 15:54

题目:

查询区间【L,R】中有多少数 比给定的 H 小。

分析:

我们可以这么想, H 一定会比 区间的第 X 大 ,第 X +1 小。
怎么确定 X。
这是一个单调的问题, 所以二分 + 区间第 K 大就可以确定了。

Code:

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;const int maxn = 100000 + 131;int sorted[maxn];int tree[30][maxn];int toleft[30][maxn];void Build(int l, int r, int dep) {    if(l == r) return ;    int mid = (l + r) >> 1;    int same = mid - l + 1;    for(int i = l; i <= r; ++i) if(tree[dep][i] < sorted[mid]) same--;    int lpos = l, rpos = mid + 1;    for(int i = l; i <= r; ++i) {        if(tree[dep][i] < sorted[mid])            tree[dep+1][lpos++] = tree[dep][i];        else if(tree[dep][i] == sorted[mid] && same > 0)            tree[dep+1][lpos++] = tree[dep][i], same--;        else tree[dep+1][rpos++] = tree[dep][i];        toleft[dep][i] = toleft[dep][l-1] + lpos - l;    }    Build(l,mid,dep+1), Build(mid+1, r, dep+1);}int Query(int L, int R, int l, int r, int dep, int k) {    if(l == r) return tree[dep][l];    int mid = (L + R) >> 1;    int cnt = toleft[dep][r] - toleft[dep][l-1];    if(cnt >= k) {        int newl = L + toleft[dep][l-1]-toleft[dep][L-1];        int newr = newl + cnt -1;        return Query(L,mid,newl, newr,dep+1, k);    }    else {        int newr = r + toleft[dep][R] - toleft[dep][r];        int newl = newr -(r-l-cnt);        return Query(mid+1,R, newl, newr,dep+1, k-cnt);    }}int main() {    int n, m, T;    ios::sync_with_stdio(false);    cin >> T;    for(int kase = 1; kase <= T; ++kase) {        memset(tree,0,sizeof(tree));        cin >> n >> m;        for(int i = 1; i <= n; ++i)            cin >> tree[0][i], sorted[i] = tree[0][i];        sort(sorted+1, sorted+1+n);        Build(1,n,0);        printf("Case %d:\n",kase);        while(m--) {            int s, t, h;            cin >> s >> t >> h;            s++, t++;            int ans = 0;            int l = 1, r = (t-s) + 1;            while(l <= r) {                int mid = (l + r) >> 1;                int temp = Query(1,n,s,t,0,mid);                if(temp <= h) {                    ans = mid;                    l = mid + 1;                }                else r = mid - 1;            }            printf("%d\n",ans);        }    }    return 0;}
0 0
原创粉丝点击