在洛谷在线 IDE 测没问题,在本地测直接 RE……。
尝试扩充系统栈后仍不行。代码如下:
// Problem: P3380 【模板】二逼平衡树(树套树)
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3380
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <algorithm>
using namespace std;
char buf[1<<14],*p1=buf,*p2=buf;
#define GetC() ((p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++)
struct Ios{}io;
template <typename _tp>
Ios &operator >>(Ios &in,_tp &x){
x=0;int w=0;char c=GetC();
for(;!isdigit(c);w|=c=='-',c=GetC());
for(;isdigit(c);x=x*10+(c^'0'),c=GetC());
if(w) x=-x;
return in;
}
const int N1=1e5*30+5,N2=1e5*30+5,inf=2147483647;
int val[N1],key[N1],sz[N1],ch[N1][2];
int sta[N1],top;
struct fhq_treap{
int rt;
fhq_treap(){rt=0;}
int new_node(int v){
int x=sta[top];--top;
val[x]=v;key[x]=rand();sz[x]=1;ch[x][0]=ch[x][1]=0;
return x;
}
void maintain(int p){
sz[p]=sz[ch[p][0]]+sz[ch[p][1]]+1;
}
void split(int p,int v,int &x,int &y){
if(!p){x=y=0;return ;}
if(val[p]<=v) x=p,split(ch[p][1],v,ch[x][1],y);
else y=p,split(ch[p][0],v,x,ch[y][0]);
maintain(p);
}
int merge(int x,int y){
if(!x||!y) return x^y;
if(key[x]>key[y]){
ch[x][1]=merge(ch[x][1],y);
maintain(x);
return x;
}
else{
ch[y][0]=merge(x,ch[y][0]);
maintain(y);
return y;
}
}
void ins(int v){
int x,y;split(rt,v,x,y);
rt=merge(merge(x,new_node(v)),y);
}
void del(int v){
int x,y,z;split(rt,v,x,z);split(x,v-1,x,y);
sta[++top]=y;y=merge(ch[y][0],ch[y][1]);
rt=merge(merge(x,y),z);
}
int num(int l,int r){
int x,y,z;split(rt,r,x,z);split(x,l-1,x,y);
int ans=sz[y];
rt=merge(merge(x,y),z);
return ans;
}
};
int cnt;
struct Seg_node{
fhq_treap treap;
int lc,rc;
}tr[N2<<1];
void Ins(int &p,int l,int r,int q,int k){
if(!p) p=++cnt;
tr[p].treap.ins(k);
if(l==r) return ;
int mid=(l+r)>>1;
if(q<=mid) Ins(tr[p].lc,l,mid,q,k);
else Ins(tr[p].rc,mid+1,r,q,k);
}
void Del(int p,int l,int r,int q,int k){//q:Ȩֵ k:λÖÃ
if(!p) return ;
tr[p].treap.del(k);
if(l==r) return ;
int mid=(l+r)>>1;
if(q<=mid) Del(tr[p].lc,l,mid,q,k);
else Del(tr[p].rc,mid+1,r,q,k);
}
int rk(int p,int l,int r,int ql,int qr,int x){
if(!p) return 0;
if(l>x) return 0;
if(r<=x){
return tr[p].treap.num(ql,qr);
}
int mid=(l+r)>>1;
if(x<=mid) return rk(tr[p].lc,l,mid,ql,qr,x);
else return rk(tr[p].lc,l,mid,ql,qr,x)+rk(tr[p].rc,mid+1,r,ql,qr,x);
}
int kth(int p,int l,int r,int ql,int qr,int k){
if(!p) return -inf;
if(tr[p].treap.num(ql,qr)<k) return -inf;
if(l==r){
if(tr[p].treap.num(ql,qr)>=k) return l;
else return -inf;
}
int mid=(l+r)>>1;
if(tr[p].lc){
int tmp=tr[tr[p].lc].treap.num(ql,qr);
if(tmp>=k) return kth(tr[p].lc,l,mid,ql,qr,k);
else return kth(tr[p].rc,mid+1,r,ql,qr,k-tmp);
}
else return kth(tr[p].rc,mid+1,r,ql,qr,k);
}
int a[N1/30];
int main(){
srand(19260817);
for(int i=N1-5;i>=1;--i) sta[++top]=i;
int n,m;io>>n>>m;
int R;
for(int i=1;i<=n;++i){
io>>a[i];
Ins(R,0,1e8,a[i],i);
}
while(m--){
int opt;io>>opt;
int l,r,k,x;
switch(opt){
case 1:
io>>l>>r>>k;
printf("%d\n",rk(R,0,1e8,l,r,k-1)+1);
break;
case 2:
io>>l>>r>>k;
printf("%d\n",kth(R,0,1e8,l,r,k));
break;
case 3:
io>>l>>k;
Del(R,0,1e8,a[l],l);
Ins(R,0,1e8,k,l);
a[l]=k;
break;
case 4:
io>>l>>r>>k;
x=rk(R,0,1e8,l,r,k-1);
if(x==0){
printf("%d\n",-inf);
}
else{
printf("%d\n",kth(R,0,1e8,l,r,x));
}
break;
case 5:
io>>l>>r>>k;
x=rk(R,0,1e8,l,r,k);
if(x>=r-l+1){
printf("%d\n",inf);
}
else{
printf("%d\n",kth(R,0,1e8,l,r,x+1));
}
break;
default :;
}
}
return 0;
}