题意
求给定序列经过给定排序网络后的第k个元素
鏼爷16年论文小例题%%%
二分答案x,原数列中大于等于x的设为1,小于x的设为0。
每一次排序的区间[l,r]中,有k1个0,k2个1,那么升序就把前k1个覆盖为0,后k2个覆盖为1,降序相反。
可以用线段树维护。
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 100010
using namespace std;
int n,m,q;
int A[N],B[N];
struct stp{
int l,r,op;
}s[N];
struct lisan{
int x,g;
friend bool operator <(lisan a,lisan b){return a.x<b.x;}
}L[N];
struct sigt{
int l,r,z,o,flg;
}T[N<<2];
inline void reaD(int &x){
char Ch=getchar();x=0;
for(;Ch>'9'||Ch<'0';Ch=getchar());
for(;Ch>='0'&&Ch<='9';x=x*10+Ch-'0',Ch=getchar());
}
inline void upd(int g){
T[g].z=T[g<<1].z+T[g<<1|1].z;
T[g].o=T[g<<1].o+T[g<<1|1].o;
}
inline void Set(int g,int w){
if(w==1) T[g].z=T[g].r-T[g].l+1,T[g].o=0;
else T[g].o=T[g].r-T[g].l+1,T[g].z=0;
T[g].flg=w;
}
inline void pushdown(int g){
if(!T[g].flg) return;
Set(g<<1,T[g].flg);
Set(g<<1|1,T[g].flg);
T[g].flg=0;
}
void build(int g,int l,int r){
T[g].l=l;T[g].r=r;T[g].flg=0;
if(l==r){
if(B[l]) T[g].o=1,T[g].z=0;
else T[g].o=0,T[g].z=1;
return ;
}
int mid=l+r>>1;
build(g<<1,l,mid);
build(g<<1|1,mid+1,r);
upd(g);
}
int query(int g,int l,int r,int w){
if(T[g].l==l&&T[g].r==r) return w==1?T[g].o:T[g].z;
pushdown(g);
int mid=T[g].l+T[g].r>>1;
if(r<=mid) return query(g<<1,l,r,w);
if(l>mid) return query(g<<1|1,l,r,w);
return query(g<<1,l,mid,w)+query(g<<1|1,mid+1,r,w);
}
void cover(int g,int l,int r,int w){
if(T[g].l==l&&T[g].r==r){Set(g,w);return;}
pushdown(g);
int mid=T[g].l+T[g].r>>1;
if(r<=mid) cover(g<<1,l,r,w);
else if(l>mid) cover(g<<1|1,l,r,w);
else cover(g<<1,l,mid,w),cover(g<<1|1,mid+1,r,w);
upd(g);
}
inline bool check(int x){
for(int i=1;i<=n;i++) B[i]=A[i]>=x;
build(1,1,n);
for(int i=1;i<=m;i++){
int z=query(1,s[i].l,s[i].r,0),o=s[i].r-s[i].l+1-z;
if(!z||!o) continue;
if(s[i].op) cover(1,s[i].l,s[i].l+o-1,2),cover(1,s[i].r-z+1,s[i].r,1);
else cover(1,s[i].r-o+1,s[i].r,2),cover(1,s[i].l,s[i].l+z-1,1);
}
return query(1,q,q,1);
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
reaD(n); reaD(m);
for(int i=1;i<=n;i++) reaD(A[i]);
for(int i=1;i<=m;i++) reaD(s[i].op),reaD(s[i].l),reaD(s[i].r);
reaD(q); int l=1,r=n,mid,Ans;
while(l<=r) check(mid=l+r>>1)?Ans=mid,l=mid+1:r=mid-1;
return printf("%d\n",Ans),0;
}