这题神啊orz
我们二分答案,把大于等于x的变成1,小于x的变成0。对于01序列去排序我们就可以直接得出排序结果啦!于是我们用线段树维护一下,每次把l~r升序排序,就先统计出l~r有多少个0,多少个1,然后把0都放在前面即可。降序同理。
#include
#include
#include
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,m,a[N],pos,ans;
struct node{
int n0,n1,tag;
friend node operator+(node a,node b){
node res;res.tag=-1;
res.n0=a.n0+b.n0;res.n1=a.n1+b.n1;return res;
}
}tr[N<<2];
struct quer{
int op,l,r;
}qq[N];
inline void pushdown(int p,int l,int r){
if(tr[p].tag==-1) return;tr[p<<1].tag=tr[p<<1|1].tag=tr[p].tag;
int mid=l+r>>1,len=mid-l+1;
if(!tr[p].tag){
int num=tr[p].n0>=len?len:tr[p].n0;
tr[p<<1].n0=num;tr[p<<1].n1=len-num;
tr[p<<1|1].n0=tr[p].n0-tr[p<<1].n0;
tr[p<<1|1].n1=tr[p].n1-tr[p<<1].n1;
}else{
int num=tr[p].n1>=len?len:tr[p].n1;
tr[p<<1].n1=num;tr[p<<1].n0=len-num;
tr[p<<1|1].n0=tr[p].n0-tr[p<<1].n0;
tr[p<<1|1].n1=tr[p].n1-tr[p<<1].n1;
}tr[p].tag=-1;
}
inline void build(int p,int l,int r){
tr[p].n0=tr[p].n1=0;tr[p].tag=-1;
if(l==r){a[l]>=ans?tr[p].n1=1:tr[p].n0=1;return;}
int mid=l+r>>1;build(p<<1,l,mid);build(p<<1|1,mid+1,r);
tr[p]=tr[p<<1]+tr[p<<1|1];
}
inline void change(int p,int l,int r,int x,int y,int op,int n0,int n1){
if(x==l&&r==y){tr[p].tag=op;tr[p].n0=n0;tr[p].n1=n1;return;}
int mid=l+r>>1;pushdown(p,l,r);
if(y<=mid) change(p<<1,l,mid,x,y,op,n0,n1);
else if(x>mid) change(p<<1|1,mid+1,r,x,y,op,n0,n1);
else{
if(!op){
int len=mid-x+1,num=n0>=len?len:n0;
change(p<<1,l,mid,x,mid,op,num,len-num);
change(p<<1|1,mid+1,r,mid+1,y,op,n0-num,n1-(len-num));
}else{
int len=mid-x+1,num=n1>=len?len:n1;
change(p<<1,l,mid,x,mid,op,len-num,num);
change(p<<1|1,mid+1,r,mid+1,y,op,n0-(len-num),n1-num);
}
}tr[p]=tr[p<<1]+tr[p<<1|1];
}
inline node ask(int p,int l,int r,int x,int y){
if(x==l&&r==y) return tr[p];
int mid=l+r>>1;pushdown(p,l,r);
if(y<=mid) return ask(p<<1,l,mid,x,y);
if(x>mid) return ask(p<<1|1,mid+1,r,x,y);
return ask(p<<1,l,mid,x,mid)+ask(p<<1|1,mid+1,r,mid+1,y);
}
inline bool ask1(int p,int l,int r,int x){
if(l==r) return tr[p].n1;
int mid=l+r>>1;pushdown(p,l,r);
if(x<=mid) return ask1(p<<1,l,mid,x);
return ask1(p<<1|1,mid+1,r,x);
}
inline bool jud(int x){
ans=x;build(1,1,n);
for(int i=1;i<=m;++i){
node res=ask(1,1,n,qq[i].l,qq[i].r);
change(1,1,n,qq[i].l,qq[i].r,qq[i].op,res.n0,res.n1);
}return ask1(1,1,n,pos);
}
int main(){
// freopen("sort.in","r",stdin);
// freopen("sort.out","w",stdout);
n=read();m=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=m;++i) qq[i].op=read(),qq[i].l=read(),qq[i].r=read();
pos=read();int l=1,r=n;
while(l<=r){
int mid=l+r>>1;
if(jud(mid)) l=mid+1;
else r=mid-1;
}printf("%d\n",l-1);
return 0;
}