/*
zoj 2112
线段树好题!!!
这题和poj2104不同的是要修改,修改的时候在区间里用
二分的方法找到和被修改的数相同的那个数,然后再用
二分法找到修改之后的数的正确位置。
欢迎各位编程爱好者加我,最近被不少编程题困住了!希望得到各位的帮助
*/
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 50001;
struct node{
int l, r;
}seg[N * 3];
int a[N], tree[20][N], n;
void build(int id, int l, int r, int dep){
seg[id].l = l;
seg[id].r = r;
if(l < r){
int mid = (l + r) / 2;
build(2 * id + 1, l, mid, dep + 1);
build(2 * id + 2, mid + 1, r, dep + 1);
//归并
int ll, rr, p;
ll = l;
rr = mid + 1;
p = l;
while(p <= r){
if(rr > r || (ll <= mid && tree[dep + 1][ll] <= tree[dep + 1][rr])){
tree[dep][p] = tree[dep + 1][ll];
p++;
ll++;
}else{
tree[dep][p] = tree[dep + 1][rr];
p++;
rr++;
//printf("r: %d/n", tree[dep][p - 1]);
}
}
}else if(l == r){
tree[dep][r] = a[r];
}
}
void output(int id, int dep){
printf("(%d, %d):", seg[id].l, seg[id].r);
for(int j = seg[id].l; j <= seg[id].r; j++)
printf("%d ", tree[dep][j]);
printf("/n");
if(seg[id].l < seg[id].r){
output(2 * id + 1, dep + 1);
output(2 * id + 2, dep + 1);
}
}
int check(int id, int key, int l, int r, int dep){
if(seg[id].l == l && seg[id].r == r){
//找比key小的数的个数
if(key <= tree[dep][l])
return 0;
if(key > tree[dep][r])
return r - l + 1;
int low = l, high = r, mid;
//找第一个不比key小的数的位置
while(low <= high){
mid = (low + high) / 2;
if(tree[dep][mid] < key)
low = mid + 1;
else
high = mid - 1;
}
return low - l;
}else{
int mid = (seg[id].l + seg[id].r) / 2;
int ans = 0;
if(l <= mid) ans += check(2 * id + 1, key, l, min(mid, r), dep + 1);
if(r > mid) ans += check(2 * id + 2, key, max(mid + 1, l), r, dep + 1);
return ans;
}
}
int query(int k, int l, int r){
int low, high, mid, num;
low = 1;
high = n;
k--;
while(low <= high){
mid = (low + high) / 2;
num = check(0, tree[0][mid], l, r, 0);
//printf("key: %d num: %d/n", tree[0][mid], num);
if(num <= k)
low = mid + 1;
else
high = mid - 1;
}
return tree[0][low - 1];
return 0;
}
void renew(int id, int c, int b, int dep){
if(seg[id].l <= c && c <= seg[id].r){
//找到一个和a[c]相等的数,将其改为b
int low, high, mid;
low = seg[id].l;
high = seg[id].r;
while(low <= high){
mid = (low + high) / 2;
if(tree[dep][mid] < a[c])
low = mid + 1;
else
high = mid - 1;
}
//tree[dep][low] = b;
int g = low;
if(b < tree[dep][low]){
low = seg[id].l;
high = g - 1;
//找到第一个比b大的数
while(low <= high){
mid = (low + high) / 2;
if(tree[dep][mid] < b)
low = mid + 1;
else
high = mid - 1;
}
for(int j = g - 1; j >= low; j--) tree[dep][j + 1] = tree[dep][j];
tree[dep][low] = b;
}else if(b > tree[dep][low]){
low = g + 1;
high = seg[id].r;
while(low <= high){
mid = (low + high) / 2;
if(tree[dep][mid] < b)
low = mid + 1;
else
high = mid - 1;
}
low--;
for(int j = g; j < low; j++) tree[dep][j] = tree[dep][j + 1];
tree[dep][low] = b;
}
mid = (seg[id].l + seg[id].r) / 2;
if(c <= mid)
renew(2 * id + 1, c, b, dep + 1);
else
renew(2 * id + 2, c, b, dep + 1);
}
}
int main(){
int m, i;
int l, r, k;
int c, b, t;
char op;
scanf("%d", &t);
while(t--){
scanf("%d%d", &n, &m);
for(i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(0, 1, n, 0);
//output(0, 0);
//printf("/n");
for(i = 1; i <= m; i++){
cin >>op;
if(op == 'Q'){
scanf("%d%d%d", &l, &r, &k);
printf("%d/n", query(k, l, r));
}else if(op == 'C'){
scanf("%d%d", &c, &b);
renew(0, c, b, 0);
a[c] = b;
//output(0, 0);
}
}
}
return 0;
}