[P3380](树套树板子)
维护一段区间内的排名,第k小,前驱,后继
线段树套平衡树即可
线段树上的每一个节点都建一棵平衡树维护所在的这一区间
修改和查前驱和后继就在线段树上对相应的区间进行操作即可 \(O(log^2)\)
查排名就查找每一小段区间内此数的排名求和,查询每一区间小于此数的个数,最后求和加上1(它本身)即可也能在 \(O(log^2)\) 求解
求第k小在线段树上操作不了,考虑二分答案,找排名小于等于k的数中最大的那一个 复杂度大约是 \(O(log^3)\) 的数量级
code
#include<bits/stdc++.h>
//================================================
//#define LOCAL FLANDRE KAWAII
#ifndef LOCAL
constexpr int SIZE(1<<20);
char in[SIZE],out[SIZE],*p1=in,*p2=in,*p3=out;
#define getchar() (p1==p2&&(p2=(p1=in)+fread(in,1,SIZE,stdin),p1==p2)?EOF:*p1++)
#define flush() (fwrite(out,1,p3-out,stdout))
#define putchar(x) (p3==out+SIZE&&(flush(),p3=out),*p3++=(x))
class Flush{public:~Flush(){flush();}}_;
#endif
inline int read(){
int x(0);bool f(0);char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar()) f^=ch=='-';
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
return f?x=-x:x;
}
inline void write(int x,char ch){
x<0?x=-x,putchar('-'):0;static short Sta[50],top(0);
do{Sta[++top]=x%10;x/=10;}while(x);
while(top) putchar(Sta[top--]|48);
putchar(ch);
}
//===================================================
constexpr int N(50005),INF(0x7fffffff);
int n,m;
int a[N],b[N];
int siz[N*30],ch[N*30][2],fa[N*30],cnt[N*30],val[N*30],tot;
namespace Splay{
inline void upd(int x){siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+cnt[x];}
inline bool chk(int x){return x==ch[fa[x]][1];}
inline void rotate(int x){
int f=fa[x],k=chk(x),ff=fa[f],kk=chk(f);
fa[ch[f][k]=ch[x][k^1]]=f;
fa[ch[x][k^1]=f]=x;
fa[x]=ff;if(ff) ch[ff][kk]=x;
upd(f);upd(x);
}
inline void splay(int &rt,int x,int goal=0){
for(int f=fa[x];f!=goal;rotate(x),f=fa[x])
if(fa[f]!=goal) rotate(chk(x)==chk(f)?f:x);
if(!goal) rt=x;
}
inline void find(int &rt,int x){
int now=rt;if(!now) return;
while(ch[now][x>val[now]]&&x!=val[now]) now=ch[now][x>val[now]];
splay(rt,now);
}
inline void ins(int &rt,int x){
int now=rt,f(0);
while(now&&val[now]!=x){f=now;now=ch[now][x>val[now]];}
if(now){cnt[now]++;siz[now]++;}
else{
now=++tot;val[tot]=x;cnt[tot]=siz[tot]=1;
fa[tot]=f;if(f) ch[f][x>val[f]]=tot;
}
splay(rt,now);
}
inline int Kth(int &rt,int k){
int now=rt;
while(1){
if(ch[now][0]&&k<=siz[ch[now][0]]) now=ch[now][0];
else if(k>siz[ch[now][0]]+cnt[now]){k-=siz[ch[now][0]]+cnt[now];now=ch[now][1];}
else return splay(rt,now),now;
}
}
inline int Rank(int &rt,int x){find(rt,x);int ans=siz[ch[rt][0]];if(val[rt]<x)ans+=cnt[rt];return ans;}
inline int Pre(int &rt,int x){
find(rt,x);if(val[rt]<x) return rt;
int now=ch[rt][0];
while(ch[now][1]) now=ch[now][1];
return splay(rt,now),now;
}
inline int Nxt(int &rt,int x){
find(rt,x);if(val[rt]>x) return rt;
int now=ch[rt][1];
while(ch[now][0]) now=ch[now][0];
return splay(rt,now),now;
}
inline void modify(int &rt,int x,int val){
int last=Pre(rt,x),next=Nxt(rt,x);
splay(rt,last);splay(rt,next,last);
int now=ch[next][0];
if(cnt[now]>1){cnt[now]--;siz[now]--;splay(rt,now);}
else ch[next][0]=0;
upd(next),upd(last);ins(rt,val);
}
}
namespace SMT{
#define ls rt<<1
#define rs rt<<1|1
int L[N<<2],R[N<<2],root[N<<2];
void build(int rt,int l,int r){
L[rt]=l;R[rt]=r;
Splay::ins(root[rt],-INF);Splay::ins(root[rt],INF);
for(int i=l;i<=r;++i) Splay::ins(root[rt],a[i]);
if(l==r) return;
int mid=l+r>>1;build(ls,l,mid);build(rs,mid+1,r);
}
void modify(int rt,int x,int val){
Splay::modify(root[rt],a[x],val);
if(L[rt]==R[rt]) return;
int mid=L[rt]+R[rt]>>1;
if(x<=mid) modify(ls,x,val);
else modify(rs,x,val);
}
int Qpre(int rt,int l,int r,int x){
if(R[rt]<l||L[rt]>r) return -INF;
if(L[rt]>=l&&R[rt]<=r) return val[Splay::Pre(root[rt],x)];
return std::max(Qpre(ls,l,r,x),Qpre(rs,l,r,x));
}
int Qnxt(int rt,int l,int r,int x){
if(R[rt]<l||L[rt]>r) return INF;
if(L[rt]>=l&&R[rt]<=r) return val[Splay::Nxt(root[rt],x)];
return std::min(Qnxt(ls,l,r,x),Qnxt(rs,l,r,x));
}
int Qrank(int rt,int l,int r,int x){
if(R[rt]<l||L[rt]>r) return 0;
if(L[rt]>=l&&R[rt]<=r) return Splay::Rank(root[rt],x)-1;
return Qrank(ls,l,r,x)+Qrank(rs,l,r,x);
}
}
int main(){
n=read();m=read();
for(int i=1;i<=n;++i){a[i]=read();}
SMT::build(1,1,n);
for(int i=1,opt,x,y,z,l,r;i<=m;++i){
opt=read();x=read();y=read();
switch(opt){
case 1:z=read();/*std::cout<<"1: ";*/write(SMT::Qrank(1,x,y,z)+1,'\n');break;
case 2:z=read();/*std::cout<<"2: ";*/
l=0,r=100000000;
while(l<r){
int mid=l+r+1>>1;
if(SMT::Qrank(1,x,y,mid)+1<=z) l=mid;
else r=mid-1;
}
write(l,'\n');break;
case 3:SMT::modify(1,x,y);a[x]=y;break;
case 4:z=read();/*std::cout<<"4: ";*/write(SMT::Qpre(1,x,y,z),'\n');break;
case 5:z=read();/*std::cout<<"5: ";*/write(SMT::Qnxt(1,x,y,z),'\n');break;
}
}
return 0;
}