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

题目链接:

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;
}
posted @ 2016-05-09 21:59  zhuyujiang  阅读(175)  评论(0编辑  收藏  举报