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.
#include<bits/stdc++.h>
using namespace std;
const int N=60005;
const int M=2500005;
struct node
{
char t[2];
int x,y,z;
}c[N];
int a[N],b[N],root[N],s[N],use[N];
int n,Q,tol,len;
int L[M],R[M],SUM[M];
int build(int l,int r)
{
int rt=++tol;
if(l<r)
{
int mid=(l+r)/2;
L[rt]=build(l,mid);
R[rt]=build(mid+1,r);
}
return rt;
}
int update(int pre,int l,int r,int k,int C)
{
int rt=++tol;
L[rt]=L[pre];R[rt]=R[pre];SUM[rt]=SUM[pre]+C;
if(l<r)
{
int mid=(l+r)/2;
if(k<=b[mid]) L[rt]=update(L[pre],l,mid,k,C);
else R[rt]=update(R[pre],mid+1,r,k,C);
}
return rt;
}
void add(int i,int k,int C)
{
while(i<=len)
{
s[i]=update(s[i],1,len,k,C);
i+=i&-i;
}
}
int sum(int i)
{
int ans=0;
while(i>0)
{
ans+=SUM[L[use[i]]];
i-=i&-i;
}
return ans;
}
int query(int pre,int v,int left,int right,int l,int r,int k)
{
if(l>=r) return l;
int ss=sum(right)-sum(left)+SUM[L[v]]-SUM[L[pre]];
int mid=(l+r)/2;
if(ss>=k)
{
for(int i=left;i>0;i-=i&-i) use[i]=L[use[i]];
for(int i=right;i>0;i-=i&-i) use[i]=L[use[i]];
return query(L[pre],L[v],left,right,l,mid,k);
}
else
{
for(int i=left;i>0;i-=i&-i) use[i]=R[use[i]];
for(int i=right;i>0;i-=i&-i) use[i]=R[use[i]];
return query(R[pre],R[v],left,right,mid+1,r,k-ss);
}
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&Q);
len=0;tol=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[++len]=a[i];
}
for(int i=1;i<=Q;i++)
{
scanf("%s",&c[i].t);
if(c[i].t[0]=='C')
{
scanf("%d%d",&c[i].x,&c[i].y);
b[++len]=c[i].y;
}
else
{
scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].z);
}
}
sort(b+1,b+len+1);
len=unique(b+1,b+len+1)-b-1;
root[0]=build(1,len);
for(int i=1;i<=n;i++)
root[i]=update(root[i-1],1,len,a[i],1);
memset(s,0,sizeof(s));
for(int i=1;i<=Q;i++)
{
node e=c[i];
if(c[i].t[0]=='C')
{
add(c[i].x,a[c[i].x],-1);
add(c[i].x,c[i].y,1);
a[c[i].x]=c[i].y;
}
else
{
for(int j=c[i].x-1;j>0;j-=j&-j) use[j]=s[j];
for(int j=c[i].y;j>0;j-=j&-j) use[j]=s[j];
printf("%d\n",b[query(root[c[i].x-1],root[c[i].y],c[i].x-1,c[i].y,1,len,c[i].z)]);
}
}
}
return 0;
}