题目链接:https://vjudge.net/problem/ZOJ-2112
多样例:
输入一个样例数t。
输入一个n和m。数组长度和操作数
Q l r k:查询区间[l, r]的第k小的数
C x y:修改a[x]=y

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 <bits/stdc++.h>  
using namespace std;  
#define  LL long long  
const int maxn=5e5+10, maxm=1e5+10, inf=1e9+7;  

struct node{  
    int x, y, k, type, id;  
}q[maxn+maxm*2], q1[maxn+maxm*2], q2[maxn+maxm*2];  

int n, m, tot, totx;  
int a[maxn], ans[maxn];  

struct BitTree  {  
    LL c[maxn];  
    int lowbit(int p){  
        return (p&-p);  
    }  
    void Add(int x, LL v)  
    {  
        if (!x)  
            return;  
        while (x < 500005)  
            c[x] += v, x += lowbit(x);  
    }  
    LL Ask(int x)  
    {  
        LL t = 0;  
        while (x)  
            t += c[x], x -= lowbit(x);  
        return t;  
    }  
    LL Ask(int l, int r)  
    {  
        if (l > r)  
            return 0;  
        return Ask(r) - Ask(l - 1);  
    }  
}Tree;  


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 mid=(L+R)>>1;  
    int t1=0, t2=0;  
    for(int i=ql; i<=qr; i++){//按顺序执行一边  
        if(q[i].type==1){//遇见修改  
            if(q[i].x<=mid){//<mid 对结果产生影响  
                Tree.Add(q[i].id, q[i].y);  
                q1[t1++]=q[i];  
            }  
            else{//不产生影响  
                q2[t2++]=q[i];  
            }  
        }  
        else{//遇见查询  
            int tt=Tree.Ask(q[i].x, q[i].y);//查询区间下标在[x, y]<=mid的数的个数  
            if(tt>=q[i].k) q1[t1++]=q[i];//如果>=k个  
            else{//如果<k个  
                q[i].k-=tt;  
                q2[t2++]=q[i];  
            }  
        }  
    }  
    for(int i=0; i<t1; i++) q[ql+i]=q1[i]; //把q1,q2的信息复制到q中  
    for(int i=0; i<t2; i++) q[ql+t1+i]=q2[i];  
    for(int i=0; i<t1; i++){  
        if(q1[i].type==1){  
            Tree.Add(q1[i].id, -q1[i].y);//把之前的标记清除  
        }  
    }  
    solve(ql, ql+t1-1, L, mid);//分治  
    solve(ql+t1, qr, mid+1, R);  
}  

int main(){  
    int T; scanf("%d", &T);  
    while(T--){  
        tot=totx=0;  
        scanf("%d%d", &n, &m);  
        int x, y, k;  
        char op[5];  
        for(int i=1; i<=n; i++){  
            scanf("%d", &a[i]);  
            tot++;  
            q[tot].x=a[i], q[tot].y=1, q[tot].type=1, q[tot].id=i;  
            //x:值   y:添加还是删除 type:查询还是修改 id:下标  
        }  
        for(int i=1; i<=m; i++){  
            scanf("%s", op);  
            if(op[0]=='Q'){  
                scanf("%d%d%d", &x, &y, &k);  
                tot++;  
                q[tot].x=x, q[tot].y=y, q[tot].k=k, q[tot].type=2, q[tot].id=++totx;  
            }  
            else{  
                scanf("%d%d", &x, &y);  
                tot++;  
                q[tot].x=a[x]; q[tot].y=-1; q[tot].type=1, q[tot].id=x;  
                tot++;  
                a[x]=y;  
                q[tot].x=a[x]; q[tot].y=1; q[tot].type=1, q[tot].id=x;  
            }  
        }  
        solve(1, tot, 0, inf);  
        for(int i=1; i<=totx; i++){  
            printf("%d\n", ans[i]);  
        }  
    }  

    return 0;  
}