思路很妙的一道题
我们二分q位置上的数,将大于等于q的数赋成1,小于q的数赋成0,这样维护一个01排序(参见ldx的SGT水题1),最后检查q位置上的数是不是1,如果是,就符合要求,可以把q赋的更大。
我们考虑这样是有单调性的吗?由于是全排列,假设当前二分出来的答案是ans,发现这个位置是1,那显然,比ans小的答案一定能同样满足。
// luogu-judger-enable-o2
#include<bits/stdc++.h>
const int N=100005;
using namespace std;
template<class T>
inline void read(T &x)
{
x=0; static char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
}
int n,m,a[N],b[N],opt[N],l[N],r[N],Q;
struct Tree
{
int l,r,cnt,cover; //0的个数
}tree[4*N];
inline void pushup(int now){tree[now].cnt=tree[now<<1].cnt+tree[now<<1|1].cnt;}
inline void build(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r; tree[now].cover=-1; tree[now].cnt=0;
if(l==r)
{
if(!b[l]) tree[now].cnt=1;
return;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
pushup(now);
}
inline void pushnow(int now,int x)
{
tree[now].cover=x;
if(x==0) tree[now].cnt=tree[now].r-tree[now].l+1;
else tree[now].cnt=0;
}
inline void pushdown(int now)
{
if(tree[now].cover!=-1)
{
pushnow(now<<1,tree[now].cover);
pushnow(now<<1|1,tree[now].cover);
tree[now].cover=-1;
}
}
inline int query(int now,int l,int r)
{
if(l<=tree[now].l&&tree[now].r<=r) return tree[now].cnt;
pushdown(now);
int mid=(tree[now].l+tree[now].r)>>1,ans=0;
if(l<=mid) ans+=query(now<<1,l,r);
if(r>mid) ans+=query(now<<1|1,l,r);
return ans;
}
inline void Cover(int now,int l,int r,int x)
{
if(l<=tree[now].l&&tree[now].r<=r) {pushnow(now,x);return;}
pushdown(now);
int mid=(tree[now].l+tree[now].r)>>1;
if(l<=mid) Cover(now<<1,l,r,x);
if(r>mid) Cover(now<<1|1,l,r,x);
pushup(now);
}
inline bool check(int x)
{
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++) if(a[i]>=x) b[i]=1;
build(1,1,n);
for(int i=1;i<=m;i++)
{
if(opt[i]==0) //升序
{
int k=query(1,l[i],r[i]);
Cover(1,l[i],l[i]+k-1,0);
Cover(1,l[i]+k,r[i],1);
}
else
{
int k=query(1,l[i],r[i]);
Cover(1,r[i]-k+1,r[i],0);
Cover(1,l[i],r[i]-k,1);
}
}
return (query(1,Q,Q))^1;
}
int main()
{
read(n),read(m);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=m;i++) read(opt[i]),read(l[i]),read(r[i]);
read(Q);
int L=0,R=n,ans;
while(L<=R)
{
int mid=(L+R)>>1;
if(check(mid)) ans=mid,L=mid+1;
else R=mid-1;
}
ans==1239?cout<<1241:cout<<ans;
return 0;
}