Dynamic Rankings
解题思路:和求区间内小于等于某个数得个数的做一样。不一样的只是这个值需要我们去二分找。
虽然时间上不太优秀,但是代码量小了很多,比树套树好写一点,思想也比较简单。
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define LL long long
#define N 50005
#define inf 0x3f3f3f3f
int len;
int a[N],b[N];
vector<int>v[255];
void init(int n)
{
rep(i,1,255)v[i].clear();
rep(i,1,n)sca(a[i]);
rep(i,1,n)b[i]=(i-1)/len+1;
rep(i,1,n)v[b[i]].pb(a[i]);
rep(i,1,b[n])sort(v[i].begin(),v[i].end());
}
void reset(int x)
{
int now=b[x];
v[now].clear();
for(int i=(now-1)*len+1;i<=now*len;i++)v[now].pb(a[i]);
sort(v[now].begin(),v[now].end());
}
void modify(int x,int y)
{
a[x]=y;
reset(x);
}
int query(int l,int r,int k)
{
int ans=0;
for(int i=l;i<=min(b[l]*len,r);i++)if(a[i]<=k)ans++;
if(b[l]!=b[r])
{
for(int i=(b[r]-1)*len+1;i<=r;i++)if(a[i]<=k)ans++;
}
rep(i,b[l]+1,b[r]-1)
{
int pos=upper_bound(v[i].begin(),v[i].end(),k)-v[i].begin();
ans+=pos;
}
return ans;
}
void work(int m)
{
while(m--)
{
char s[3];
int x,y,k;
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d%d%d",&x,&y,&k);
int l=1,r=1e9;
int ans;
while(l<r)
{
int m=(l+r)>>1;
if(query(x,y,m)>=k)r=m;
else l=m+1;
}
printf("%d\n",r);
}
else
{
scanf("%d%d",&x,&y);
modify(x,y);
}
}
}
int main()
{
int t;
sca(t);
while(t--)
{
int n,m;
len=sqrt(n);
sca(n),sca(m);
init(n);
work(m);
}
}