考虑二分枚举答案,变成01的一个序列,用线段树来维护排序即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 struct ji{ 8 int p,x,y; 9 }v[N]; 10 int n,m,p,x,y,a[N],f[N<<2],laz[N<<2]; 11 void upd(int k,int l,int r,int x){ 12 laz[k]=x; 13 f[k]=(r-l+1)*x; 14 } 15 void down(int k,int l,int r){ 16 if (laz[k]==-1)return; 17 upd(L,l,mid,laz[k]); 18 upd(R,mid+1,r,laz[k]); 19 laz[k]=-1; 20 } 21 void update(int k,int l,int r,int x,int y,int z){ 22 if ((l>y)||(x>r))return; 23 if ((x<=l)&&(r<=y)){ 24 upd(k,l,r,z); 25 return; 26 } 27 down(k,l,r); 28 update(L,l,mid,x,y,z); 29 update(R,mid+1,r,x,y,z); 30 f[k]=f[L]+f[R]; 31 if (laz[k]!=-1)upd(k,l,r,laz[k]); 32 } 33 int query(int k,int l,int r,int x,int y){ 34 if ((l>y)||(x>r))return 0; 35 if ((x<=l)&&(r<=y))return f[k]; 36 down(k,l,r); 37 return query(L,l,mid,x,y)+query(R,mid+1,r,x,y); 38 } 39 bool pd(int k){ 40 memset(laz,-1,sizeof(laz)); 41 update(1,1,n,1,n,0); 42 for(int i=1;i<=n;i++) 43 if (a[i]>=k)update(1,1,n,i,i,1); 44 else update(1,1,n,i,i,0); 45 for(int i=1;i<=m;i++){ 46 int x=query(1,1,n,v[i].x,v[i].y); 47 if (!v[i].p){ 48 update(1,1,n,v[i].x,v[i].y-x,0); 49 update(1,1,n,v[i].y-x+1,v[i].y,1); 50 } 51 else{ 52 update(1,1,n,v[i].x,v[i].x+x-1,1); 53 update(1,1,n,v[i].x+x,v[i].y,0); 54 } 55 } 56 return query(1,1,n,p,p); 57 } 58 int main(){ 59 scanf("%d%d",&n,&m); 60 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 61 for(int i=1;i<=m;i++){ 62 scanf("%d%d%d",&p,&x,&y); 63 v[i]=ji{p,x,y}; 64 } 65 scanf("%d",&p); 66 x=1,y=n; 67 while (x<y){ 68 int m=(x+y+1>>1); 69 if (pd(m))x=m; 70 else y=m-1; 71 } 72 printf("%d",x); 73 }