这题的思路好清奇
因为只有一次查询,我们考虑二分这个值为多少
将原序列转化为一个$01$序列,如果原序列上的值大于$mid$则为$1$否则为$0$
那么排序就可以用线段树优化,设该区间内$1$的个数为$res$,如果是升序排序,只要把$[r-res+1,r]$区间全部变为$1$,$[l,r-res]$区间全部变为$0$即可,用线段树区间覆盖即可
那么只要最后查询$k$的位置上是否是$1$,如果是的话$ans=mid,l=mid+1$,否则$r=mid-1$
考虑为什么能这样二分。我们经过这样之后,如果最后位置$k$上为$1$,那么这肯定是一个大于等于$mid$的数,否则肯定是一个小于$mid$的数
然后差不多了
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 using namespace std; 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 6 char buf[1<<21],*p1=buf,*p2=buf; 7 inline int read(){ 8 #define num ch-'0' 9 char ch;bool flag=0;int res; 10 while(!isdigit(ch=getc())) 11 (ch=='-')&&(flag=true); 12 for(res=num;isdigit(ch=getc());res=res*10+num); 13 (flag)&&(res=-res); 14 #undef num 15 return res; 16 } 17 const int N=30005; 18 struct Q{ 19 int op,l,r; 20 Q(){} 21 Q(int op,int l,int r):op(op),l(l),r(r){} 22 }q[N]; 23 int n,m,st[N],val[N],tag[N<<2],sum[N<<2],k; 24 inline void upd(int p){sum[p]=sum[p<<1]+sum[p<<1|1];} 25 inline void pd(int p,int l,int r){ 26 if(~tag[p]){ 27 tag[p<<1]=tag[p<<1|1]=tag[p]; 28 sum[p<<1]=tag[p]*l,sum[p<<1|1]=tag[p]*r; 29 tag[p]=-1; 30 } 31 } 32 void build(int p,int l,int r){ 33 tag[p]=-1; 34 if(l==r) return (void)(sum[p]=st[l]); 35 int mid=(l+r)>>1; 36 build(p<<1,l,mid),build(p<<1|1,mid+1,r); 37 upd(p); 38 } 39 void update(int p,int l,int r,int ql,int qr,int val){ 40 if(ql<=l&&qr>=r) return (void)(sum[p]=val*(r-l+1),tag[p]=val); 41 int mid=(l+r)>>1; 42 pd(p,mid-l+1,r-mid); 43 if(ql<=mid) update(p<<1,l,mid,ql,qr,val); 44 if(qr>mid) update(p<<1|1,mid+1,r,ql,qr,val); 45 upd(p); 46 } 47 int query(int p,int l,int r,int ql,int qr){ 48 if(ql<=l&&qr>=r) return sum[p]; 49 int mid=(l+r)>>1; 50 pd(p,mid-l+1,r-mid); 51 int res=0; 52 if(ql<=mid) res+=query(p<<1,l,mid,ql,qr); 53 if(qr>mid) res+=query(p<<1|1,mid+1,r,ql,qr); 54 return res; 55 } 56 int check(int mid){ 57 for(int i=1;i<=n;++i) 58 st[i]=val[i]>=mid?1:0; 59 build(1,1,n); 60 for(int i=1;i<=m;++i){ 61 int l=q[i].l,r=q[i].r; 62 if(q[i].op==0){ 63 int res=query(1,1,n,l,r); 64 update(1,1,n,r-res+1,r,1); 65 update(1,1,n,l,r-res,0); 66 }else{ 67 int res=query(1,1,n,l,r); 68 update(1,1,n,l,l+res-1,1); 69 update(1,1,n,l+res,r,0); 70 } 71 } 72 return query(1,1,n,k,k); 73 } 74 int main(){ 75 // freopen("testdata.in","r",stdin); 76 n=read(),m=read(); 77 for(int i=1;i<=n;++i) val[i]=read(); 78 for(int i=1,op,l,r;i<=m;++i) 79 op=read(),l=read(),r=read(),q[i]=Q(op,l,r); 80 k=read(); 81 int l=1,r=n,ans=0; 82 while(l<=r){ 83 int mid=(l+r)>>1; 84 if(check(mid)) l=mid+1,ans=mid;else r=mid-1; 85 } 86 printf("%d ",ans); 87 return 0; 88 }