Dynamic Rankings ZOJ - 2112
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
#include <bits/stdc++.h>
using namespace std;
const int maxn=6e4+10;
const int maxm=2500005;
int T[maxn],L[maxm],R[maxm],SUM[maxm],s[maxn],use[maxn];
int a[maxn],b[maxn],tot,num;
struct node
{
char str[2];
int x,y,z;
}c[maxn];
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int ans=0;
while(x>0)
{
ans+=SUM[L[use[x]]];
x-=lowbit(x);
}
return ans;
}
void build(int &rt,int l,int r)
{
rt=++tot;
//SUM[rt]=0;
int mid=(l+r)/2;
if(l==r) return ;
build(L[rt],l,mid);
build(R[rt],mid+1,r);
}
void update(int &rt,int pre,int l,int r,int x,int C)
{
rt=++tot;
L[rt]=L[pre],R[rt]=R[pre],SUM[rt]=SUM[pre]+C;
int mid= (l+r)/2;
if(l==r) return;
if(x<=b[mid]) update(L[rt],L[pre],l,mid,x,C);
else update(R[rt],R[pre],mid+1,r,x,C);
}
int query(int s,int e,int left,int right,int l,int r,int k)
{
int mid=(l+r)/2;
if(l==r) return l;
int res=sum(right)-sum(left)+SUM[L[e]]-SUM[L[s]];
if(res>=k)
{
for(int i=left;i>0;i-=lowbit(i)) use[i]=L[use[i]];
for(int i=right;i>0;i-=lowbit(i)) use[i]=L[use[i]];
return query(L[s],L[e],left,right,l,mid,k);
}
else
{
for(int i=left;i>0;i-=lowbit(i)) use[i]=R[use[i]];
for(int i=right;i>0;i-=lowbit(i)) use[i]=R[use[i]];
return query(R[s],R[e],left,right,mid+1,r,k-res);
}
}
void add(int x,int k,int C)
{
while(x<=num)
{
update(s[x],s[x],1,num,k,C);
x+=lowbit(x);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(s,0,sizeof s);
int n,m;
scanf("%d%d",&n,&m);
num=0;
tot=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[++num]=a[i];
}
for(int i=1;i<=m;i++)
{
scanf("%s",c[i].str);
if(c[i].str[0]=='C')
{
scanf("%d%d",&c[i].x,&c[i].y);
b[++num]=c[i].y;
}
else
{
scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].z);
}
}
sort(b+1,b+num+1);
num=unique(b+1,b+num+1)-b-1;
build(T[0],1,num);
for(int i=1;i<=n;i++)
{
update(T[i],T[i-1],1,num,a[i],1);
}
for(int i=1;i<=m;i++)
{
if(c[i].str[0]=='C')
{
add(c[i].x,c[i].y,1);
add(c[i].x,a[c[i].x],-1);
a[c[i].x]=c[i].y;
}
else
{
for(int j=c[i].x-1;j>0;j-=lowbit(j)) use[j]=s[j];
for(int j=c[i].y;j>0;j-=lowbit(j)) use[j]=s[j];
printf("%d\n",b[query(T[c[i].x-1],T[c[i].y],c[i].x-1,c[i].y,1,num,c[i].z)]);
}
}
}
return 0;
}