ZOJ 2112 Dynamic Rankings (动态第 K 大)(树状数组套主席树)

Dynamic Rankings

Time Limit: 10 Seconds      Memory Limit: 32768 KB

The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.

Your task is to write a program for this computer, which

- Reads N numbers from the input (1 <= N <= 50,000)

- Processes M instructions of the input (1 <= M <= 10,000). These instructions include querying the k-th smallest number of a[i], a[i+1], ..., a[j] and change some a[i] to t.


Input

The first line of the input is a single number X (0 < X <= 4), the number of the test cases of the input. Then X blocks each represent a single test case.


The first line of each block contains two integers N and M, representing N numbers and M instruction. It is followed by N lines. The (i+1)-th line represents the number a[i]. Then M lines that is in the following format

Q i j k or
C i t

It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change some a[i] to t, respectively. It is guaranteed that at any time of the operation. Any number a[i] is a non-negative integer that is less than 1,000,000,000.

There're NO breakline between two continuous test cases.


Output

For each querying operation, output one integer to represent the result. (i.e. the k-th smallest number of a[i], a[i+1],..., a[j])

There're NO breakline between two continuous test cases.


Sample Input

2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3


Sample Output

3
6
3
6

 表示不是很懂,先插个眼。。

#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<cstdlib>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<queue>  
#include<stack>  
#include<string>  
#include<map>  
#include<set>  
#include<ctime>  
#define eps 1e-6  
#define LL long long  
#define pii (pair<int, int>)  
//#pragma comment(linker, "/STACK:1024000000,1024000000")  
using namespace std;  
  
//zoj 2104 动态主席树修改+静态主席树   
const int maxn = 60000+1000;  
const int M = 2400000;  
int n, q, m, tot;  
int a[maxn], t[maxn];  
int T[maxn], lson[M], rson[M], c[M];  
int S[maxn];  
struct Query {  
    int kind;  
    int l, r, k;  
} query[10010];  
  
void Init_hash(int k) {  
    sort(t, t+k);  
    m = unique(t, t+k) - t;  
}  
  
int Hash(int x) {  
    return lower_bound(t, t+m, x) - t;  
}  
  
int build(int l, int r) {  
    int root = tot++;  
    c[root] = 0;  
    if(l != r) {  
        int mid = (l+r) >> 1;  
        lson[root] = build(l, mid);  
        rson[root] = build(mid+1, r);  
    }  
    return root;  
}  
  
int Insert(int root, int pos, int val) {  
    int newroot = tot++, tmp = newroot;  
    int l = 0, r = m-1;  
    c[newroot] = c[root] + val;  
    while(l < r) {  
        int mid = (l+r)>>1;  
        if(pos <= mid) {  
            lson[newroot] = tot++; rson[newroot] = rson[root];  
            newroot = lson[newroot]; root = lson[root];  
            r = mid;  
        }  
        else {  
            rson[newroot] = tot++; lson[newroot] = lson[root];  
            newroot = rson[newroot]; root = rson[root];  
            l = mid+1;  
        }  
        c[newroot] = c[root] + val;  
    }  
    return tmp;  
}  
  
int lowbit(int x) {  
    return x&(-x);  
}  
int use[maxn];  
void add(int x, int pos, int d) {  
    while(x <= n) {  
        S[x] = Insert(S[x], pos, d);  
        x += lowbit(x);  
    }  
}  
int Sum(int x) {  
    int ret = 0;  
    while(x > 0) {  
        ret += c[lson[use[x]]];  
        x -= lowbit(x);  
    }  
    return ret;  
}  
int Query(int left, int right, int k) {  
    int left_root = T[left-1], right_root = T[right];  
    int l = 0, r = m-1;  
    for(int i = left-1; i; i -= lowbit(i)) use[i] = S[i];  
    for(int i = right; i; i -= lowbit(i)) use[i] = S[i];  
    while(l < r) {  
        int mid = (l+r) >> 1;  
        int tmp = Sum(right) - Sum(left-1) + c[lson[right_root]] - c[lson[left_root]];  
        if(tmp >= k) {  
            r = mid;  
            for(int i = left-1; i; i -= lowbit(i)) use[i] = lson[use[i]];  
            for(int i = right; i; i -= lowbit(i)) use[i] = lson[use[i]];  
            left_root = lson[left_root];  
            right_root = lson[right_root];  
        }  
        else {  
            l = mid + 1;  
            k -= tmp;  
            for(int i = left-1; i; i -= lowbit(i)) use[i] = rson[use[i]];  
            for(int i = right; i; i -= lowbit(i)) use[i] = rson[use[i]];  
            left_root = rson[left_root];  
            right_root = rson[right_root];  
        }         
    }  
    return l;  
}  
  
int main() {  
    //freopen("input.txt", "r", stdin);  
    int Tcase; cin >> Tcase;   
    while(Tcase--) {  
        scanf("%d%d", &n, &q);  
        tot = 0;  
        m = 0;  
        for(int i = 1; i <= n; i++) {  
            scanf("%d", &a[i]);  
            t[m++] = a[i];  
        }  
        char op[10];  
        for(int i = 0;i < q;i++) {  
            scanf("%s",op);  
            if(op[0] == 'Q') {  
                query[i].kind = 0;  
                scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k);  
            }  
            else {  
                query[i].kind = 1;  
                scanf("%d%d", &query[i].l, &query[i].r);  
                t[m++] = query[i].r;  
            }  
        }  
        Init_hash(m);  
        T[0] = build(0, m-1);  
        for(int i = 1; i <= n; i++) T[i] = Insert(T[i-1], Hash(a[i]), 1);  
        for(int i = 1; i <= n; i++) S[i] = T[0];  
        for(int i = 0; i < q; i++) {  
            if(query[i].kind == 0) printf("%d
",t[Query(query[i].l,query[i].r,query[i].k)]);  
            else {  
                add(query[i].l, Hash(a[query[i].l]), -1);  
                add(query[i].l, Hash(query[i].r), 1);  
                a[query[i].l] = query[i].r;  
            }  
        }         
    }  
    return 0;  
}  
原文地址:https://www.cnblogs.com/jianrenfang/p/6375947.html