ZOJ 2112 动态第k大 主席树+树状数组

来源:互联网 发布:观鲸 知乎 编辑:程序博客网 时间:2024/04/27 14:23
/*    ZOJ 2112 动态第k大        考虑静态第k大的主席树做法,第i棵树T[i]保存的是数组前i个元素的信息    对询问(i,j,k),只用取出T[j]和T[i-1]即可        若数组元素有修改,做法也差不多    令T[i]只记录数组前i个元素的信息    修改a[i]=j的时候,需对所有k>=i的T[k]修改    对询问,也只用取出T[j]和T[i-1]即可    上述操作类似树状数组,所以没必要真的修改那么对T[k]啦        代码参考自        http://www.cnblogs.com/kuangbin/p/3308118.html*/#include <cstdio>#include <algorithm>#define m (l+r)/2using namespace std;const int N = 51100;const int M = N * 50;int n, q, num, a[N], b[2*N], l, r, k;int T[N], S[N], cnt[M], lson[M], rson[M], tot;int hash(int a){ return lower_bound(b, b + num, a) - b + 1; }struct que{    char ch;    int i,j,k;}Q[N];int init(int l, int r){    int root = tot ++;    cnt[root] = 0;    if(l < r) lson[root] = init(l, m), rson[root] = init(m + 1, r);    return root;}int upd(int pre_root, int pos, int val){    int cur_root = tot ++, ret = cur_root;      cnt[cur_root] = cnt[pre_root] + val;    int l = 1, r = num;    while(r > l){        if(pos <= m){            rson[cur_root] = rson[pre_root];            cur_root = lson[cur_root] = tot ++;            pre_root = lson[pre_root];            cnt[cur_root] = cnt[pre_root] + val;            r = m;        }        else {            lson[cur_root] = lson[pre_root];            cur_root = rson[cur_root] = tot ++;            pre_root = rson[pre_root];            cnt[cur_root] = cnt[pre_root] + val;            l = m + 1;        }    }    return ret;}void UPDATE(int pos, int val, int d){    for( ; pos <= n ; pos += pos & -pos)        T[pos] = upd(T[pos], val, d);}int use[N];int query(int pre, int cur, int k){    int l = 1, r = num, P = pre, C = cur, pp = S[pre], cc = S[cur];    for(pre = P; pre > 0 ; pre -= pre & -pre) use[pre] = T[pre];    for(cur = C; cur > 0 ; cur -= cur & -cur) use[cur] = T[cur];    while(r > l){        int left_sum = cnt[lson[pp]], right_sum = cnt[lson[cc]];        for(pre = P; pre > 0 ; pre -= pre & -pre) left_sum += cnt[lson[use[pre]]];        for(cur = C; cur > 0 ; cur -= cur & -cur) right_sum += cnt[lson[use[cur]]];        if(k <= right_sum - left_sum){            for(pre = P; pre > 0 ; pre -= pre & -pre) use[pre] = lson[use[pre]];            for(cur = C; cur > 0 ; cur -= cur & -cur) use[cur] = lson[use[cur]];            pp = lson[pp];            cc = lson[cc];            r = m;        }        else {            k -= right_sum - left_sum;            for(pre = P; pre > 0 ; pre -= pre & -pre) use[pre] = rson[use[pre]];            for(cur = C; cur > 0 ; cur -= cur & -cur) use[cur] = rson[use[cur]];            pp = rson[pp];            cc = rson[cc];            l = m + 1;        }    }    return l&r;}int main(){    int t;    scanf("%d", &t);    while(t --){        scanf("%d %d", &n, &q);        num = 0;        for(int i = 1; i <= n; i ++) scanf("%d",&a[i]), b[num++] = a[i];        for(int i = 0; i < q; i ++) {            scanf(" %c%d%d", &Q[i].ch, &Q[i].i, &Q[i].j);            if(Q[i].ch == 'Q') scanf("%d", &Q[i].k);            else b[num++] = Q[i].j;        }        sort(b, b + num);        num = unique(b , b + num) - b;        tot = 0;        S[0] = T[0] = init(1, num);        for(int i = 1; i <= n ; i ++) S[i] = upd(S[i-1], hash(a[i]), 1), T[i] = T[0];        for(int i = 0; i < q; i ++) {            if(Q[i].ch == 'Q'){                printf("%d\n", b[query(Q[i].i - 1, Q[i].j, Q[i].k)- 1] );            }            else {                UPDATE(Q[i].i, hash(a[Q[i].i]), -1);                UPDATE(Q[i].i, hash(a[Q[i].i] = Q[i].j), 1);            }        }    }}

0 0