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
【解题报告】
分块SB题
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 50010
#define inf 1e9
int t,n,m;
int sz,num;
int pos[N],L[N],R[N];
int a[N],b[N];
void resort(int x)
{
for(int i=L[x];i<=R[x];++i) b[i]=a[i];
sort(b+L[x],b+R[x]+1);
}
void init()
{
sz=sqrt(n);num=n/sz;
if(n%num) ++num;
for(int i=1;i<=n;++i) pos[i]=(i-1)/sz+1;
for(int i=1;i<=num;++i)
{
L[i]=(i-1)*sz+1;
R[i]=i*sz;
}
R[num]=n;
for(int i=1;i<=num;++i) resort(i);
}
void update(int x,int v)
{
a[x]=v;
resort(pos[x]);
}
int query(int l,int r,int v)
{
int ans=0,lb=pos[l],rb=pos[r];
if(lb==rb)
{
for(int i=l;i<=r;++i) if(a[i]<=v) ++ans;
}
else
{
for(int i=l;i<=R[lb];++i) if(a[i]<=v) ++ans;
for(int i=lb+1;i<=rb-1;++i) ans+=upper_bound(b+L[i],b+R[i]+1,v)-(b+L[i]);
for(int i=L[rb];i<=r;++i) if(a[i]<=v) ++ans;
}
return ans;
}
int main()
{
for(scanf("%d",&t);t;--t)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
init();
for(int i=1;i<=m;++i)
{
char opt[5];scanf("%s",opt);
if(opt[0]=='Q')
{
int a,b,k;scanf("%d%d%d",&a,&b,&k);
int l=1,r=inf,res;
while(l<=r)
{
int mid=(l+r)>>1;
if(query(a,b,mid)>=k) r=mid-1,res=mid;
else l=mid+1;
}
printf("%d\n",res);
}
if(opt[0]=='C')
{
int a,b;scanf("%d%d",&a,&b);
update(a,b);
}
}
}
return 0;
}