ZOJ 1112 Dynamic Rankings【动态区间第K大,整体二分】

来源:互联网 发布:修道士和野人问题java 编辑:程序博客网 时间:2024/05/17 02:04

题目链接:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112

题意:

求动态区间第K大。

分析:

把修改操作看成删除与增加,对所有操作进行整体二分。

代码:

#include<cstdio>#include<iostream>#include<cstring>using namespace std;#define pr(x) cout << #x << ": " << x << "  "#define pl(x) cout << #x << ": " << x << endl;const int maxn = 50000 + 5, maxq = 20000 + 5, oo = 0x3f3f3f3f;int n, m, tot;int a[maxn];struct Query{    int x, y, k;    int id, type;}q[maxn + maxq], q1[maxn + maxq], q2[maxn + maxq];int bit[maxn];int ans[maxq];void add(int i, int x){    while(i <= n){        bit[i] += x;        i += i & -i;    }}int sum(int i){    int ans = 0;    while(i > 0){        ans += bit[i];        i -= i & -i;    }    return ans;}void solve(int ql, int qr, int l, int r){    if(ql > qr) return ;    if(l == r){        for(int i = ql; i <= qr; i++){            if(q[i].type == 2) ans[q[i].id] = l;        }        return ;    }    int t1 = 0, t2 = 0;    int mid = l + r >> 1;   // pl(mid);    for(int i = ql; i <= qr; i++){        if(q[i].type == 1){            if(q[i].x <= mid){                add(q[i].id, q[i].y);                q1[t1++] = q[i];            }else q2[t2++] = q[i];        }else{            int tmp = sum(q[i].y) -sum(q[i].x - 1);            if(tmp >= q[i].k) q1[t1++] = q[i];            else {                    q[i].k -= tmp;                    q2[t2++] = q[i];            }        }    }    for(int i = 0; i < t1; i++){        if(q1[i].type == 1) add(q1[i].id, -q1[i].y);    }    for(int i = 0; i < t1; i++) q[ql + i] = q1[i];    for(int i = 0; i < t2; i++) q[t1 + i + ql] = q2[i];    solve(ql, ql + t1 - 1, l, mid);    solve(ql + t1, qr, mid + 1, r);}int main (void){    int x;scanf("%d", &x);    while(x--){        scanf("%d%d", &n, &m);        tot = 0;        memset(bit, 0, sizeof(bit));        for(int i = 1; i <= n; i++){            scanf("%d", &a[i]);            q[++tot] = (Query){a[i], 1, oo, i, 1};        }        char s[2];        int x, y, k;        int cnt = 0;        for(int i = 1; i <= m; i++){            scanf("%s%d%d", s, &x, &y);            if(s[0] == 'Q'){                scanf("%d", &k);                q[++tot] = (Query){x, y, k, ++cnt, 2};            }else{                q[++tot] = (Query){a[x], -1, oo, x, 1};                q[++tot] = (Query){y, 1, oo, x, 1};            }        }        solve(1, tot, 0, oo);        for(int i = 1; i <= cnt; i++){            printf("%d\n", ans[i]);        }    }    return 0;}
0 0
原创粉丝点击