线段树套平衡树做法;
#include<bits/stdc++.h>
#define ls x<<1
#define rs x<<1|1
using namespace std;
const int N=200005;
const int M=3000001;
const int inf=0x3f3f3f3f;
int root[N],sum[M],s[M],ch[M][2],val[M],key[M],n,m,tot=0,a[N];
inline void up(int x){s[x]=sum[x]+s[ch[x][0]]+s[ch[x][1]];
}
int newnode(int x,int v){int t=++tot;ch[t][0]=ch[t][1]=0;val[t]=v;key[t]=rand();sum[t]=s[t]=1;return t;
}
void rotate(int& x,int d){
int t=ch[x][d^1];ch[x][d^1]=ch[t][d];ch[t][d]=x,up(x),up(t),x=t;
}
void insert(int &x,int v){
if(!x){x=newnode(x,v);return;}
if(val[x]==v){sum[x]++;up(x);return;}
int d=(val[x]<v);
insert(ch[x][d],v);
if(key[ch[x][d]]<key[x])rotate(x,d^1);
up(x);
}
void del(int &x,int v){if(!x)return;
if(val[x]==v){
if(sum[x]>1){sum[x]--;up(x);return;}
else{
if(ch[x][0]*ch[x][1]==0){int k=ch[x][1]+ch[x][0];x=k;return;}
int d=(key[ch[x][0]]<key[ch[x][1]]);
rotate(x,d);del(ch[x][d],v);
}
}
del(ch[x][val[x]<v],v);
up(x);
}
int getrank(int x,int v){if(!x)return 0;
if(val[x]==v)return s[ch[x][0]];
if(val[x]<v)return s[ch[x][0]]+sum[x]+getrank(ch[x][1],v);
else return getrank(ch[x][0],v);
}
int getpro(int x,int v){if(!x)return -inf;
if(val[x]<v)return max(val[x],getpro(ch[x][1],v));
else return getpro(ch[x][0],v);
}
int getaft(int x,int v){if(!x)return inf;
if(val[x]>v)return min(val[x],getaft(ch[x][0],v));
else return getaft(ch[x][1],v);
}
void build(int x,int l,int r,int pos,int v){
insert(root[x],v);
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)build(ls,l,mid,pos,v);
else build(rs,mid+1,r,pos,v);
}
int rank(int x,int l,int r,int ql,int qr,int v){int ans=0;
if(l>=ql && r<=qr){return getrank(root[x],v);}
int mid=(l+r)>>1;
if(ql<=mid)ans+=rank(ls,l,mid,ql,qr,v);
if(qr>mid)ans+=rank(rs,mid+1,r,ql,qr,v);
return ans;
}
int kth(int ql,int qr,int k){
int l=0,r=inf,ans;
while(l<=r){int mid=(l+r)>>1;
if(rank(1,1,n,ql,qr,mid)<=k-1){l=mid+1;ans=mid;} ///
else r=mid-1;
}
return ans;
}
void change(int x,int l,int r,int pos,int v){
del(root[x],a[pos]);insert(root[x],v);
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)change(ls,l,mid,pos,v);
else change(rs,mid+1,r,pos,v);
}
int pro(int x,int l,int r,int ql,int qr,int v){int ans=-inf;
if(l>=ql && r<=qr){return getpro(root[x],v);}
int mid=(l+r)>>1;
if(ql<=mid)ans=max(ans,pro(ls,l,mid,ql,qr,v));
if(qr>mid)ans=max(ans,pro(rs,mid+1,r,ql,qr,v));
return ans;
}
int aft(int x,int l,int r,int ql,int qr,int v){int ans=inf;
if(l>=ql && r<=qr){return getaft(root[x],v);}
int mid=(l+r)>>1;
if(ql<=mid)ans=min(ans,aft(ls,l,mid,ql,qr,v));
if(qr>mid)ans=min(ans,aft(rs,mid+1,r,ql,qr,v));
return ans;
}
void debug(int x) {
if(!x)return;
debug(ch[x][0]);
printf("%d :( val: %d sum: %d size: %d ls:%d rs: %d)\n",x,val[x], sum[x],s[x], ch[x][0], ch[x][1]);
debug(ch[x][1]);
}
void bug(int x,int l,int r){
printf("root[%d] %d %d \n",x,l,r);debug(root[x]);
if(l==r)return;
int mid=(l+r)>>1;
bug(ls,l,mid);bug(rs,mid+1,r);
}
int main(){
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)build(1,1,n,i,a[i]);
for(int i=1;i<=m;i++)
{
int f;scanf("%d",&f);
int x,y,k;
switch(f)
{
case 1:scanf("%d%d%d",&x,&y,&k);printf("%d\n",rank(1,1,n,x,y,k)+1);break;
case 2:scanf("%d%d%d",&x,&y,&k);printf("%d\n",kth(x,y,k));break;
case 3:scanf("%d%d",&x,&y);change(1,1,n,x,y);a[x]=y;break;
case 4:scanf("%d%d%d",&x,&y,&k);printf("%d\n",pro(1,1,n,x,y,k));break;
case 5:scanf("%d%d%d",&x,&y,&k);printf("%d\n",aft(1,1,n,x,y,k));break;
}
}
// printf("\n\n");bug(1,1,n);
return 0;
}
好慢…难道说这题的意思是用平衡树的都是…….