ZOJ 2112 Dynamic Rankings

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18964

动态求区间第k大,树状数组套主席树,终于会了。还需要多练

感谢博主的代码帮忙
http://www.cnblogs.com/kuangbin/p/3308118.html

真的不好讲,建议学习的直接看代码。

My code

//Hello. I'm Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

#define N 50010
#define M 10010
#define MAXN 2500010
int n, m, a[N], tot, Tid[N], Uid[N], uid[N];

int temp[N + M], numtemp;
int getemp(int x){
    return (int)(lower_bound(temp + 1, temp + 1 + numtemp, x) - temp);
}

struct Oper{
    char ty;
    int i,j,k,t;
}oper[M];

#define mid ((l+r)>>1)
struct Segment_Tree{
    int sum;
    int lson, rson;
}tree[MAXN];

int init_big_tree(int l,int r){
    int id = tot++;
    tree[id].sum = 0;

    if(l == r) return id;

    tree[id].lson = init_big_tree(l, mid);
    tree[id].rson = init_big_tree(mid + 1, r);

    return id;
}

int update_tree(int faid,int p,int l,int r,int v){
    int id = tot++;
    tree[id] = tree[faid];
    tree[id].sum += v;

    if(l == r) return id;

    if(p <= mid) tree[id].lson = update_tree(tree[faid].lson, p, l, mid, v);
    else tree[id].rson = update_tree(tree[faid].rson, p, mid + 1, r, v);

    return id;
}

int calsum(int p,int nowid){
    int ans = 0;
    for(int i = p; i>0; i -= i&-i){
        int lsid = tree[ uid[i] ].lson;
        ans += tree[ lsid ].sum;
    }

    int lsid = tree[ nowid ].lson;
    ans += tree[ lsid ].sum;

    return ans;
}

int query_kth(int l,int r,int fr,int to,int frid,int toid,int k){
    if(l == r) return l;

    int k1 = calsum(to, toid) - calsum(fr, frid);

    if(k1 >= k){
        for(int i = to; i>0 ; i -= i&-i) uid[i] = tree[ uid[i] ].lson;
        for(int i = fr; i>0 ; i -= i&-i) uid[i] = tree[ uid[i] ].lson;

        return query_kth(l, mid, fr, to, tree[frid].lson, tree[toid].lson, k);
    }
    else{
        for(int i = to; i>0 ; i -= i&-i) uid[i] = tree[ uid[i] ].rson;
        for(int i = fr; i>0 ; i -= i&-i) uid[i] = tree[ uid[i] ].rson;

        return query_kth(mid + 1, r, fr, to, tree[frid].rson, tree[toid].rson, k - k1);
    }
}

void update(int fr,int to,int v,int val){
    for(int i = fr; i <= to; i += i&-i){
        Uid[i] = update_tree(Uid[i], v, 1, numtemp, val);
    }
}

#define input freopen("/Users/peteryuanpan/data.txt","r",stdin)

int main(){
    //input;

    int T = read();
    for(int kase = 1; kase <= T; kase++){
        n = read(), m = read();
        numtemp = 0;

        for(int i = 1; i <= n; i++){
            a[i] = read();
            temp[++numtemp] = a[i];
        }

        for(int i = 1; i <= m; i++){
            char tty[10];
            scanf("%s",tty);

            oper[i].ty = tty[0];
            if(tty[0] == 'Q'){
                oper[i].i = read(), oper[i].j = read(), oper[i].k = read();
            }
            else{
                oper[i].i = read(), oper[i].t = read();
                temp[++numtemp] = oper[i].t;
            }
        }

        sort(temp + 1, temp + 1 + numtemp);
        numtemp = (int)(unique(temp + 1, temp + 1 + numtemp) - (temp + 1));
        for(int i = 1; i <= n; i++) a[i] = getemp(a[i]);
        for(int i = 1; i <= m; i++) if(oper[i].ty == 'C') oper[i].t = getemp(oper[i].t);

        tot = 0;
        Tid[0] = init_big_tree(1, numtemp);
        for(int i = 1; i <= n; i++){
            Tid[i] = update_tree(Tid[i-1], a[i], 1, numtemp, +1);
        }
        for(int i = 1; i <= n; i++){
            Uid[i] = Tid[0];
        }

        for(int im = 1; im <= m; im++){
            if(oper[im].ty == 'Q'){
                int fr = oper[im].i, to = oper[im].j;
                for(int i = fr - 1; i>0; i -= i&-i) uid[i] = Uid[i];
                for(int i = to; i>0; i -= i&-i) uid[i] = Uid[i];
                int a = query_kth(1, numtemp, fr - 1, to, Tid[fr - 1], Tid[to], oper[im].k);

                printf("%d\n",temp[a]);
            }
            else{
                int p = oper[im].i, v = oper[im].t;
                update(p, n, a[p], -1);
                update(p, n, v, +1);

                a[p] = v;
            }
        }
    }

    return 0;
}






你可能感兴趣的:(主席树套树状数组,动态求区间第k大)