ZOJ - 2112 Dynamic Rankings

题意:

  给出一个长度为N的序列。M次操作,Q代表询问区间的第K大值,C代表修改一个位置的数。输出每次询问的第K大值。

题解:

  修改第i个位置的数会影响i~n。所以可以用树状数组维护每次修改。树状数组的每个节点代表一棵树,统计结果时对应位置相加即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 60010;
int t;
int n, m, num;
int w[maxn];
int tot;
int root[maxn];
char tt[2];
vector<int> v;
struct ask {
    int t, l, r, v;
}q[10010];
struct node {
    int l, r, sum;
}tre[maxn*40];
int use[maxn], tree[maxn];
int getid(int x) {
    return lower_bound(v.begin(), v.end(), x)-v.begin()+1;
}
void update(int l, int r, int &x, int y, int pos, int val) {
    tre[++tot] = tre[y];
    tre[tot].sum += val;
    x = tot;
    if(l==r) return ;
    int mid = l+r>>1;
    if(pos<=mid) update(l, mid, tre[x].l, tre[y].l, pos, val);
    else update(mid+1, r, tre[x].r, tre[y].r, pos, val);
}
void add(int x, int pos, int val) {
    while(x <= n) {
        update(1, num, tree[x], tree[x], pos, val);
        x += x&(-x);
    }
}
int sum(int x) {
    int res = 0;
    while(x) {
        res += tre[tre[use[x]].l].sum;
        x -= x&(-x);
    }
    return res;
}
int query(int l, int r, int x, int y, int k, int ql, int qr) {
    if(l==r) return l;
    int mid = l+r>>1;
    int t = tre[tre[x].l].sum-tre[tre[y].l].sum+sum(qr)-sum(ql);
    if(t>=k) {
        for(int i = qr; i; i-=i&(-i)) 
        use[i] = tre[use[i]].l;
        for(int i = ql; i; i-=i&(-i)) 
        use[i] = tre[use[i]].l;
        return query(l, mid, tre[x].l, tre[y].l, k, ql, qr);
    }
    else {
        for(int i = qr; i > 0; i-=i&(-i)) 
        use[i] = tre[use[i]].r;
        for(int i = ql; i > 0; i-=i&(-i)) 
        use[i] = tre[use[i]].r;
        return query(mid+1, r, tre[x].r, tre[y].r, k-t, ql, qr);
    }
}
int main() {
    scanf("%d", &t);
    while(t--) {
        tot = 0;
        v.clear();
        memset(tree, 0, sizeof(tree));
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &w[i]);
            v.push_back(w[i]);
        }
        for(int i = 1; i <= m; i++) {
            scanf("%s%d%d", tt, &q[i].l, &q[i].r);
            if(tt[0]=='C') q[i].t = 0, v.push_back(q[i].r);
            else scanf("%d", &q[i].v), q[i].t = 1;
        }
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        num = v.size();
        for(int i = 1; i <= n; i++) update(1, num, root[i], root[i-1], getid(w[i]), 1);
        for(int i = 1; i <= m; i++) {
            if(q[i].t) {
                for(int j = q[i].r; j; j-=j&(-j)) 
                use[j] = tree[j];
                for(int j = q[i].l-1; j; j-=j&(-j))
                use[j] = tree[j];
                printf("%d\n", v[query(1, num, root[q[i].r], root[q[i].l-1], q[i].v, q[i].l-1, q[i].r)-1]);
            }
            else {
                add(q[i].l, getid(w[q[i].l]), -1);
                add(q[i].l, getid(q[i].r), 1);
                w[q[i].l] = q[i].r; 
            }
        }
    }
}
View Code

 

posted @ 2018-04-30 13:21  Pneuis  阅读(178)  评论(0编辑  收藏  举报