Sol
写法同动态第k大
查询前驱后继有一些细节注意
Code
// by spli
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define LL long long
using namespace std;
const int N=50010;
int n,m,r[N<<1],sz;
LL a[N],b[N<<1],top,len;
struct Tree{
int ls,rs;
int siz;
}t[N*200];
struct ques{
LL op,x,y,z;
}q[N];
int lft[N],rgh[N],A,B;
int lowbit(int x){return x&(-x);}
void update(int &p,int L,int R,int k,int d){
//t[++sz]=t[p];
//p=sz;
if(!p) p=++sz;
t[p].siz+=d;
if(L==R) return;
int mid=(L+R)>>1;
if(k<=mid) update(t[p].ls,L,mid,k,d);
else update(t[p].rs,mid+1,R,k,d);
}
void add(int pos,int k,int d){
for(int i=pos;i<=n;i+=lowbit(i))
update(r[i],1,len,k,d);
}
void ready(int L,int R){
L--;
A=B=0;
for(int i=L;i;i-=lowbit(i)) lft[++A]=r[i];
for(int i=R;i;i-=lowbit(i)) rgh[++B]=r[i];
}
void getlft(){
for(int i=1;i<=A;++i) lft[i]=t[lft[i]].ls;
for(int i=1;i<=B;++i) rgh[i]=t[rgh[i]].ls;
}
void getrgh(){
for(int i=1;i<=A;++i) lft[i]=t[lft[i]].rs;
for(int i=1;i<=B;++i) rgh[i]=t[rgh[i]].rs;
}
int getsum(){
int ret=0;
for(int i=1;i<=A;++i) ret-=t[t[lft[i]].ls].siz;
for(int i=1;i<=B;++i) ret+=t[t[rgh[i]].ls].siz;
return ret;
}
int getrank(int L,int R,int v){
if(L==R) return 1;
int mid=(L+R)>>1;
if(mid>=v){
getlft();
return getrank(L,mid,v);
}
else{
int sum=getsum();
getrgh();
return sum+getrank(mid+1,R,v);
}
}
int get_th(int L,int R,int k){
if(L==R) return L;
int mid=(L+R)>>1;
int sum=getsum();
if(k<=sum) return getlft(),get_th(L,mid,k);
else return getrgh(),get_th(mid+1,R,k-sum);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%lld",&a[i]),b[++top]=a[i];
for(int i=1;i<=m;++i){
scanf("%lld%lld%lld",&q[i].op,&q[i].x,&q[i].y);
if(q[i].op==3) b[++top]=q[i].y;
else{
scanf("%lld",&q[i].z);
if(q[i].op==4||q[i].op==5) b[++top]=q[i].z;
}
}
b[++top]=2147483647;
b[++top]=-2147483647;
sort(b+1,b+1+top);
len=unique(b+1,b+1+top)-b-1;
for(int i=1;i<=n;++i){
int rk=lower_bound(b+1,b+1+len,a[i])-b;
add(i,rk,1);
}
for(int i=1;i<=m;++i){
if(q[i].op==1){
ready(q[i].x,q[i].y);
q[i].z=lower_bound(b+1,b+1+len,q[i].z)-b;
printf("%d\n",getrank(1,len,q[i].z));
}
if(q[i].op==2){
ready(q[i].x,q[i].y);
printf("%d\n",b[get_th(1,len,q[i].z)]);
}
if(q[i].op==3){
int rk=lower_bound(b+1,b+1+len,a[q[i].x])-b;
add(q[i].x,rk,-1);
rk=lower_bound(b+1,b+1+len,q[i].y)-b;
add(q[i].x,rk,1);
a[q[i].x]=q[i].y;
}
//lower_bound查的是第一个大于等于x的数,一次求前驱可以 get_th(1,len,rk-1)
// 后继必须 get_th(1,len,rk+num)
if(q[i].op==4){
ready(q[i].x,q[i].y);
q[i].z=lower_bound(b+1,b+1+len,q[i].z)-b;
int rk=getrank(1,len,q[i].z);
ready(q[i].x,q[i].y);
printf("%d\n",b[get_th(1,len,rk-1)]);
}
if(q[i].op==5){
q[i].z=lower_bound(b+1,b+1+len,q[i].z)-b;
ready(q[i].x,q[i].y);
int rk=getrank(1,len,q[i].z);
int num=-rk;
ready(q[i].x,q[i].y);
num+=getrank(1,len,q[i].z+1);
ready(q[i].x,q[i].y);
printf("%d\n",b[get_th(1,len,rk+num)]);
}
}
return 0;
}