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继续回答上面的问题。
Input
第一行有两个正整数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
m,n≤10000
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
tip
root[i]:数组下标是i的元素在主席树中的编号
在处理询问的时候,需要两个辅助数组,记录一下需要查询的root
一定要看好变量名
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=200010;
struct node{
int l,r,sum;
};
node t[N*40];
int V[N],a[N],val[N],n,m,cnt,top=0,root[N],Le[N],Ri[N],cntl,cntr;
struct po{
int type,x,y,k;
};
po Q[N];
void change(int &now,int L,int R,int x,int z)
{
top++;
t[top]=t[now];
now=top;
t[top].sum+=z;
if (L==R) return; ///
int M=(L+R)>>1;
if (x<=M) change(t[now].l,L,M,x,z); //x是权值
else change(t[now].r,M+1,R,x,z);
}
int ask(int L,int R,int k)
{
if (L==R) return L;
int suml=0,sumr=0;
for (int i=1;i<=cntl;i++)
suml+=t[t[Le[i]].l].sum;
for (int i=1;i<=cntr;i++)
sumr+=t[t[Ri[i]].l].sum;
int M=(L+R)>>1;
if (sumr-suml>=k) //左儿子
{
for (int i=1;i<=cntl;i++)
Le[i]=t[Le[i]].l;
for (int i=1;i<=cntr;i++)
Ri[i]=t[Ri[i]].l;
return ask(L,M,k);
}
else
{
for (int i=1;i<=cntl;i++)
Le[i]=t[Le[i]].r;
for (int i=1;i<=cntr;i++)
Ri[i]=t[Ri[i]].r;
return ask(M+1,R,k-(sumr-suml));
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
val[i]=a[i]; //原数组
}
cnt=n;
char s[10];
for (int i=1;i<=m;i++)
{
scanf("%s",s);
if (s[0]=='C')
{
scanf("%d%d",&Q[i].x,&Q[i].y);
Q[i].type=1; //修改
a[++cnt]=Q[i].y;
}
else
{
scanf("%d%d%d",&Q[i].x,&Q[i].y,&Q[i].k);
Q[i].x--;
Q[i].type=2;
}
}
sort(a+1,a+1+cnt);
cnt=unique(a+1,a+1+cnt)-a-1; //离散后的元素个数
for (int i=1;i<=cnt;i++)
V[i]=a[i];
for (int i=1;i<=n;i++)
{
int num=lower_bound(a+1,a+1+cnt,val[i])-a; //离散后的值
for (int j=i;j<=n;j+=(j&(-j)))
change(root[j],1,cnt,num,1); //j lowbit(j)都要change
}
for (int i=1;i<=m;i++)
{
if (Q[i].type==1) //修改
{
int num=lower_bound(a+1,a+1+cnt,val[Q[i].x])-a;
for (int j=Q[i].x;j<=n;j+=(j&(-j)))
change(root[j],1,cnt,num,-1);
num=lower_bound(a+1,a+1+cnt,Q[i].y)-a;
for (int j=Q[i].x;j<=n;j+=(j&(-j)))
change(root[j],1,cnt,num,1);
val[Q[i].x]=Q[i].y; //更改值
}
else //询问
{
cntl=cntr=0;
for (int j=Q[i].x;j>0;j-=(j&(-j))) Le[++cntl]=root[j]; //记录一下需要查询的root
for (int j=Q[i].y;j>0;j-=(j&(-j))) Ri[++cntr]=root[j];
printf("%d\n",V[ask(1,cnt,Q[i].k)]); //(L,R) 二分的是答案
}
}
return 0;
}