题目链接:https://loj.ac/problem/2055
二分答案之后变为01序列,每次排序直接将区间赋值为1或者0即可,用线段树维护即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
template<typename Tp>
struct seg
{
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
Tp tr[MAXN<<2],lazy[MAXN<<2];
inline void push_up(int rt)
{
tr[rt]=tr[rt<<1]+tr[rt<<1|1];
}
inline void push_down(int l,int r,int rt)
{
if(lazy[rt]!=-1)
{
int mid=(l+r)>>1;
tr[rt<<1]=(mid-l+1)*lazy[rt];
tr[rt<<1|1]=(r-mid)*lazy[rt];
lazy[rt<<1]=lazy[rt];
lazy[rt<<1|1]=lazy[rt];
lazy[rt]=-1;
}
}
void build(int l,int r,int rt,int *a)
{
lazy[rt]=-1;
if(l==r)
{
tr[rt]=a[l];
return;
}
int mid=(l+r)>>1;
build(lson,a);
build(rson,a);
push_up(rt);
}
void update(int L,int R,Tp val,int l,int r,int rt)
{
if(L>R) return;
if(L<=l&&r<=R)
{
tr[rt]=(r-l+1)*val;
lazy[rt]=val;
return ;
}
push_down(l,r,rt);
int mid=(l+r)>>1;
if(L<=mid)
update(L,R,val,lson);
if(mid<R)
update(L,R,val,rson);
push_up(rt);
}
Tp query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return tr[rt];
push_down(l,r,rt);
int mid=(l+r)>>1;
Tp ret=0;
if(L<=mid)
ret+=query(L,R,lson);
if(mid<R)
ret+=query(L,R,rson);
return ret;
}
};
struct operatation
{
int op,l,r;
}sv[MAXN];
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void rea(int &x)
{
char c=nc();x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
seg<int> se;
int a[MAXN],p[MAXN];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,m,k;
rea(n);rea(m);
for(int i=1;i<=n;i++)
{
rea(a[i]);
}
for(int i=1;i<=m;i++)
{
rea(sv[i].op);rea(sv[i].l);rea(sv[i].r);
}
rea(k);
int l=1,r=n,ans=1;
while(l<=r)
{
int mid=(l+r)>>1;
for(int i=1;i<=n;i++)
{
p[i]=(a[i]>=mid);
}
se.build(1,n,1,p);
for(int i=1;i<=m;i++)
{
int op=sv[i].op;
int l=sv[i].l;
int r=sv[i].r;
int cnt=se.query(l,r,1,n,1);
//cout<<cnt<<" "<<r-l+1<<endl;
if(op==0)
{
se.update(r-cnt+1,r,1,1,n,1);
se.update(l,r-cnt,0,1,n,1);
}
else
{
se.update(l+cnt,r,0,1,n,1);
se.update(l,l+cnt-1,1,1,n,1);
}
}
int num=se.query(k,k,1,n,1);
//cout<<mid<<endl;
if(num)
{
ans=mid;
l=mid+1;
}
else
{
r=mid-1;
}
}
printf("%d\n",ans);
return 0;
}