线段树套平衡树
没什么好讲的,直接码就完了。
#include<bits/stdc++.h>
#define ll long long
#define db double
#define filein(a) freopen(#a".in","r",stdin)
#define fileot(a) freopen(#a".out","w",stdout)
#define Better_IO false
namespace IO{
#if Better_IO
char buf[(1<<20)+3],*p1(buf),*p2(buf);
const int lim=1<<20;
inline char gc(){
if(p1==p2) p2=(p1=buf)+fread(buf,1,lim,stdin);
return p1==p2?EOF:*p1++;
}
#define pc putchar
#else
#define gc getchar
#define pc putchar
#endif
inline bool blank(char c){
return c=='\t' or c=='\n' or c=='\r' or c==' ' or c==EOF;
}
inline void gs(char *s){
char ch=gc();
while(blank(ch) ) ch=gc();
while(!blank(ch) ) {*s++=ch;ch=gc();}
*s=0;
}
inline void ps(char *s){
while(*s!=0) {pc(*s++);}
}
template<class T>
inline void read(T &s){
s=0;char ch=gc();bool f=0;
while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();}
while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();}
if(ch=='.'){
db p=0.1;ch=gc();
while('0'<=ch&&ch<='9') {s=s+p*(ch^48);ch=gc();p*=0.1;}
}
s=f?-s:s;
}
template<class T,class ...A>
inline void read(T &s,A &...a){
read(s);read(a...);
}
};
using IO::gs;
using IO::ps;
using IO::read;
const int N=5e4+3;
const int inf=1e9;
int n,m;
int a[N];
struct Scapegoat{
#define lc(x) t[x].lc
#define rc(x) t[x].rc
const db alpha=0.7;
int tot;
struct node{
int lc,rc,cnt;
int k,sz,fc;
}t[(N<<1)*16*16];
inline void pushup(int x){
t[x].sz=t[lc(x)].sz+t[rc(x)].sz+1;
t[x].fc=t[lc(x)].fc+t[rc(x)].fc+t[x].cnt;
}
inline bool canrbu(int x){
return t[x].cnt and (
t[x].sz*alpha<=(db)std::max(t[lc(x)].sz,t[rc(x)].sz) or
(db)t[x].fc<=t[x].sz*alpha
);
}
int top,fd[(N<<1)*16];
void rbu_ldr(int x){
if(!x) return;
rbu_ldr(lc(x) );
if(t[x].cnt) fd[++top]=x;
rbu_ldr(rc(x) );
}
int rbu_build(int l,int r){
if(l>r) return 0;
int mid=(l+r)>>1;
lc(fd[mid])=rbu_build(l,mid-1);
rc(fd[mid])=rbu_build(mid+1,r);
pushup(fd[mid]);
return fd[mid];
}
inline void rbu(int &x){
top=0;rbu_ldr(x);
x=rbu_build(1,top);
}
void ins(int &x,int k){
if(!x){
x=++tot;
t[x].k=k;
++t[x].cnt;
pushup(x);
return;
}
if(t[x].k==k){
++t[x].cnt;
}else if(t[x].k<k){
ins(rc(x),k);
}else{
ins(lc(x),k);
}
pushup(x);
if(canrbu(x) ) rbu(x);
}
void del(int &x,int k){
if(!x) return;
if(t[x].k==k){
if(t[x].cnt) --t[x].cnt;
}else if(t[x].k<k){
del(rc(x),k);
}else{
del(lc(x),k);
}
pushup(x);
if(canrbu(x) ) rbu(x);
}
int upper(int x,int k){
if(!x) return 0;
if(t[x].k==k) return t[lc(x)].fc;
if(k<t[x].k) return upper(lc(x),k);
return t[lc(x)].fc+t[x].cnt+upper(rc(x),k);
}
int kth(int x,int k){
if(!x) return 0;
if(t[lc(x)].fc<k and k<=t[lc(x)].fc+t[x].cnt)
return t[x].k;
if(k<=t[lc(x)].fc) return kth(lc(x),k);
return kth(rc(x),k-t[lc(x)].fc-t[x].cnt);
}
inline int pre(int x,int k){
int s=upper(x,k);
if(s<=0) return -inf;
return kth(x,s);
}
inline int nxt(int x,int k){
int s=upper(x,k+1)+1;
if(s>t[x].fc) return inf;
return kth(x,s);
}
#undef lc
#undef rc
}s2;
struct SegTree{
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
struct node{
int l,r,mid;
int rt;
}t[N<<2];
inline void build(int x,int l,int r){
t[x].l=l;t[x].r=r;t[x].mid=(l+r)>>1;
for(int i=l;i<=r;++i){
s2.ins(t[x].rt,a[i]);
}
if(l==r){
return;
}
build(lc(x),l,t[x].mid);
build(rc(x),t[x].mid+1,r);
}
inline int upper(int x,int l,int r,int k){
if(l<=t[x].l and t[x].r<=r){
return s2.upper(t[x].rt,k);
}
int res=0;
if(l<=t[x].mid) res+=upper(lc(x),l,r,k);
if(t[x].mid+1<=r) res+=upper(rc(x),l,r,k);
return res;
}
inline void modify(int x,int p,int a,int b){
s2.del(t[x].rt,a);
s2.ins(t[x].rt,b);
if(p<=t[x].l and t[x].r<=p){
return;
}
if(p<=t[x].mid) modify(lc(x),p,a,b);
if(t[x].mid+1<=p) modify(rc(x),p,a,b);
}
inline int pre(int x,int l,int r,int k){
if(l<=t[x].l and t[x].r<=r){
return s2.pre(t[x].rt,k);
}
int res=-inf;
if(l<=t[x].mid) res=std::max(res,pre(lc(x),l,r,k) );
if(t[x].mid+1<=r) res=std::max(res,pre(rc(x),l,r,k) );
return res;
}
inline int nxt(int x,int l,int r,int k){
if(l<=t[x].l and t[x].r<=r){
return s2.nxt(t[x].rt,k);
}
int res=inf;
if(l<=t[x].mid) res=std::min(res,nxt(lc(x),l,r,k) );
if(t[x].mid+1<=r) res=std::min(res,nxt(rc(x),l,r,k) );
return res;
}
#undef lc
#undef rc
}s1;
int main(){
//filein(a);fileot(a);
read(n,m);
for(int i=1;i<=n;++i){
read(a[i]);
}
s1.build(1,1,n);
for(int i=1;i<=m;++i){
int op;read(op);
int l,r,p,k;
int t=clock();
if(op==1){
read(l,r,k);
printf("%d\n",s1.upper(1,l,r,k)+1);
}
if(op==2){
read(l,r,k);
int el=0,er=1e8,eres=0;
int tim=0;
while(el<=er){
++tim;
int emid=(el+er)>>1;
if(s1.upper(1,l,r,emid)<k){
el=emid+1;eres=emid;
}else er=emid-1;
}
printf("%d\n",eres);
}
if(op==3){
read(p,k);
s1.modify(1,p,a[p],k);
a[p]=k;
}
if(op==4){
read(l,r,k);
int s=s1.pre(1,l,r,k);
if(s!=-inf)
printf("%d\n",s);
else printf("-2147483647\n");
}
if(op==5){
read(l,r,k);
int s=s1.nxt(1,l,r,k);
if(s!=inf)
printf("%d\n",s);
else printf("2147483647\n");
}
}
fprintf(stderr,"%dms\n",clock() );
return 0;
}