Description
给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。
Input
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
Output
Sample Input
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
6
题意:求区间第K小值,值可变更
思路:不要求修改的区间第K小值问题中,主席树的每棵线段树维护前缀或者后缀的位置的情况。可修改,也就是单点更新的话就不能这样了。因为每次修改的话会导致前缀或者后缀的所有线段树都要更改。具体是主席树的每颗线段树只维护树状数组上一个区间的位置的情况,前缀和的统计用树状数组来实现。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 20080
#define maxm 5500000
#define lowbit(x) x&(-x)
int T[maxn],Tnow[maxn],key[maxn<<1],X[maxn<<1];
int lson[maxm],rson[maxm],c[maxm];
int tot,n,cnt;
int build(int l,int r)
{
int root = tot++,tmp = root;
if(l != r)
{
int mid = (l+r) >> 1;
lson[root] = build(l,mid);
rson[root] = build(mid+1,r);
}
return tmp;
}
int update(int root,int pos,int val)
{
int newnode = tot++,tmp = newnode;
int l = 1,r = cnt;
while(l < r)
{
int mid = (l + r) >> 1;
if(pos <= mid)
{
lson[newnode] = tot++,rson[newnode] = rson[root];
root = lson[root],newnode = lson[newnode];
r = mid;
}
else
{
lson[newnode] = lson[root],rson[newnode] = tot++;
root = rson[root],newnode = rson[newnode];
l = mid+1;
}
c[newnode] = c[root] + val;
}
return tmp;
}
void query_init(int x)
{
while(x > 0)
{
Tnow[x] = T[x];
x -= lowbit(x);
}
}
int sum(int x)
{
int ret = 0;
while(x > 0)
{
ret += c[lson[Tnow[x]]];
x -= lowbit(x);
}
return ret;
}
int Query(int L,int R,int k)
{
query_init(L-1),query_init(R);
int l = 1,r = cnt;
while(l < r)
{
int mid = (l+r) >> 1;
int temp = sum(R) - sum(L-1);
if(temp >= k)
{
int x = L-1,y = R;
while(x > 0)
{
Tnow[x] = lson[Tnow[x]];
x -= lowbit(x);
}
while(y > 0)
{
Tnow[y] = lson[Tnow[y]];
y -= lowbit(y);
}
r = mid;
}
else
{
k -= temp;
int x = L-1,y = R;
while(x > 0)
{
Tnow[x] = rson[Tnow[x]];
x -= lowbit(x);
}
while(y > 0)
{
Tnow[y] = rson[Tnow[y]];
y -= lowbit(y);
}
l = mid+1;
}
}
return l;
}
struct Que
{
char ope;
int u,v,k;
Que(){}
Que(char c,int uu,int kk)
{
ope = c,u = uu,k = kk;
}
Que(char c,int uu,int vv,int kk)
{
ope = c,u = uu,v = vv,k = kk;
}
}que[maxn];
int main()
{
//freopen("in.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)==2)
{
for(int i = 1;i <= n;i++)
scanf("%d",&key[i]);
cnt = n;
for(int i = 1;i <= m;i++)
{
char ope[2];
int u,v,k;
scanf("%s",ope);
if(ope[0] == 'Q')
{
scanf("%d%d%d",&u,&v,&k);
que[i] = Que(ope[0],u,v,k);
}
else
{
scanf("%d%d",&u,&k);
que[i] = Que(ope[0],u,k);
key[++cnt] = k;
}
}
memcpy(X,key,sizeof(key));
sort(X+1,X+1+cnt);
T[0] = build(1,cnt);
for(int i = 1;i <= n;i++) T[i] = T[0];
for(int i = 1;i <= n;i++)
{
int x = lower_bound(X+1,X+1+cnt,key[i]) - X;
for(int j = i;j <= cnt;j += lowbit(j))
{
T[j] = update(T[j],x,1);
}
}
for(int i = 1;i <= m;i++)
{
if(que[i].ope == 'C')
{
int x = que[i].u;
int y = lower_bound(X+1,X+1+cnt,key[x]) - X;
while(x <= cnt)
{
T[x] = update(T[x],y,-1);
x += lowbit(x);
}
x = que[i].u,y = lower_bound(X+1,X+1+cnt,que[i].k) - X;
key[x] = que[i].k;
while(x <= cnt)
{
T[x] = update(T[x],y,1);
x += lowbit(x);
}
}
else
{
printf("%d\n",X[Query(que[i].u,que[i].v,que[i].k)]);
}
}
}
return 0;
}