线段树套treap
#include<cstdio> #include<cctype> #include<algorithm> #define maxn 200001 #define maxm 3000002 using namespace std; int n,m,size,res,a[maxn],root[maxn]; int ls[maxm],rs[maxm],rnd[maxm],w[maxm],siz[maxm],v[maxm]; inline void read(int &x){ char ch=getchar();x=0;int f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} x*=f; } inline void updata(int x){siz[x]=siz[ls[x]]+siz[rs[x]]+w[x];} inline void rturn(int &x){int tmp=ls[x];ls[x]=rs[tmp];rs[tmp]=x;siz[tmp]=siz[x];updata(x);x=tmp;} inline void lturn(int &x){int tmp=rs[x];rs[x]=ls[tmp];ls[tmp]=x;siz[tmp]=siz[x];updata(x);x=tmp;} inline void insert(int &k,int num){ if(!k){k=++size;siz[k]=w[k]=1;v[k]=num;rnd[k]=rand();return;} siz[k]++; if(num==v[k])w[k]++; else if(num<v[k]){insert(ls[k],num);if(rnd[ls[k]]<rnd[k])rturn(k);} else{insert(rs[k],num);if(rnd[rs[k]]<rnd[k])lturn(k);} } inline void buildtr(int k,int l,int r,int x,int num){ insert(root[k],num); if(l==r)return; int mid=(l+r)>>1; if(x<=mid)buildtr(k<<1,l,mid,x,num);else buildtr(k<<1|1,mid+1,r,x,num); } inline void del(int &k,int num){ if(v[k]==num){ if(w[k]>1){w[k]--;siz[k]--;return;} if(ls[k]*rs[k]==0)k=ls[k]+rs[k]; else if(rnd[ls[k]]<rnd[rs[k]]){rturn(k);del(k,num);} else {lturn(k);del(k,num);} } else if(num<v[k]){del(ls[k],num);siz[k]--;} else{del(rs[k],num);siz[k]--;} } inline void ask_rank(int k,int num){ if(!k)return; if(num==v[k]){res+=siz[ls[k]];return;} else if(num<v[k])ask_rank(ls[k],num); else{res+=siz[ls[k]]+w[k];ask_rank(rs[k],num);} } inline void get_rank(int k,int l,int r,int x,int y,int num){ if(l==x && r==y){ask_rank(root[k],num);return;} int mid=(l+r)>>1; if(mid>=y)get_rank(k<<1,l,mid,x,y,num); else if(mid<x)get_rank(k<<1|1,mid+1,r,x,y,num); else{ get_rank(k<<1,l,mid,x,mid,num); get_rank(k<<1|1,mid+1,r,mid+1,y,num); } } inline void get_index(int x,int y,int z){ int l=0,r=1e9,ans; while(l<=r){ int mid=(l+r)>>1; res=1;get_rank(1,1,n,x,y,mid); if(res<=z){l=mid+1;ans=mid;}else r=mid-1; } printf("%d\n",ans); } inline void change(int k,int l,int r,int x,int num,int y){ del(root[k],y); insert(root[k],num); if(l==r)return; int mid=(l+r)>>1; if(x<=mid)change(k<<1,l,mid,x,num,y);else change(k<<1|1,mid+1,r,x,num,y); } inline void get_pre(int k,int num){ if(!k)return; if(v[k]<num){res=max(v[k],res);get_pre(rs[k],num);}else get_pre(ls[k],num); } inline void get_suc(int k,int num){ if(!k)return; if(v[k]>num){res=min(res,v[k]);get_suc(ls[k],num);}else get_suc(rs[k],num); } inline void ask_after(int k,int l,int r,int x,int y,int num){ if(l==x && r==y){get_suc(root[k],num);return;} int mid=(l+r)>>1; if(mid>=y)ask_after(k<<1,l,mid,x,y,num); else if(mid<x)ask_after(k<<1|1,mid+1,r,x,y,num); else{ ask_after(k<<1,l,mid,x,mid,num); ask_after(k<<1|1,mid+1,r,mid+1,y,num); } } inline void ask_before(int k,int l,int r,int x,int y,int num){ if(l==x && r==y){get_pre(root[k],num);return;} int mid=(l+r)>>1; if(mid>=y)ask_before(k<<1,l,mid,x,y,num); else if(mid<x)ask_before(k<<1|1,mid+1,r,x,y,num); else{ ask_before(k<<1,l,mid,x,mid,num); ask_before(k<<1|1,mid+1,r,mid+1,y,num); } } int main(){ int typ,x,y,z; read(n);read(m); for(int i=1;i<=n;i++)read(a[i]); for(int i=1;i<=n;i++)buildtr(1,1,n,i,a[i]); for(int i=1;i<=m;i++){ read(typ);read(x);read(y); switch(typ){ case 1:read(z);res=1;get_rank(1,1,n,x,y,z);printf("%d\n",res);break; case 2:read(z);get_index(x,y,z);break; case 3:change(1,1,n,x,y,a[x]);a[x]=y;break; case 4:read(z);res=0;ask_before(1,1,n,x,y,z);printf("%d\n",res);break; case 5:read(z);res=1e9;ask_after(1,1,n,x,y,z);printf("%d\n",res);break; } } return 0; }