题意略。
solution
这道题目我们可以线段树加二分,
首先我们二分最终的答案,然后我们把这个序列变成0/1序列,具体而言,我们将大于等于mid的设为1,小于mid的设为0,排序的话,以升序为例,我们把0扔到左边,1扔到右边,降序类似,然后我们看一下最后我们要求的位置上是0还是1,同时缩小答案范围即可。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
using namespace std;
const int N=1e+5+55;
int s[N*4],setv[N*4],x[N],y[N],a[N],b[N],z[N];
int l,r,n,m,mid,pos,k,p,y1,y2,w;
void build(int o,int l,int r)
{
if (l==r){
setv[o]=s[o]=b[l];
return;
}
int m=l+r>>1;
build(o<<1,l,m);build(o<<1|1,m+1,r);
s[o]=s[o<<1]+s[o<<1|1];
}
void pushdown(int o)
{
if (setv[o]>=0)
{
setv[o<<1]=setv[o<<1|1]=setv[o];
setv[o]=-1;
}
}
void maintain(int o,int l,int r)
{
if (r>l) s[o]=s[o<<1]+s[o<<1|1];
if (setv[o]>=0) s[o]=setv[o]*(r-l+1);
}
void update(int o,int l,int r)
{
if (l>y2||r<y1) return;//注意一定要加
if (y1<=l&&r<=y2) setv[o]=w;
else
{
int m=l+r>>1;
pushdown(o);
if (y1<=m) update(o<<1,l,m);else maintain(o<<1,l,m);
if (m<y2) update(o<<1|1,m+1,r);else maintain(o<<1|1,m+1,r);
}
maintain(o,l,r);
}
void query(int o,int l,int r)
{
if (l>y2||r<y1) return;
if (setv[o]>=0) k+=(min(y2,r)-max(l,y1)+1)*setv[o];
else
{
if ((y1<=l)&&(r<=y2)) k+=s[o];
else
{
int m=l+r>>1;
if (y1<=m) query(o<<1,l,m);
if (m<y2) query(o<<1|1,m+1,r);
}
}
}
int main()
{
//freopen("jzoj4605.in","r",stdin);
//freopen("jzoj4605.out","w",stdout);
scanf("%d%d",&n,&m);
fo(i,1,n) scanf("%d",&a[i]);
fo(i,1,m) scanf("%d%d%d",&z[i],&x[i],&y[i]);
scanf("%d",&p);
l=1;
r=n;
int ans=0;
while (l<r)
{
mid=l+r>>1;
fo(i,1,n)
if (mid<=a[i]){
b[i]=1;
if (mid==a[i]) pos=i;
}
else b[i]=0;
memset(setv,-1,sizeof(setv));
build(1,1,n);
fo(i,1,m){
y1=x[i],y2=y[i],k=0;
query(1,1,n);
if (!z[i]){
y1=x[i],y2=y[i]-k,w=0;
update(1,1,n);
//update(x[i],y[i]-k,0);//1
y1=y[i]-k+1,y2=y[i],w=1;
update(1,1,n);
//update(y[i]-k+1,y[i],1);
if (x[i]<=pos&&pos<=y[i]) pos=y[i]-k+1;// 1
}
else{
y1=x[i],y2=x[i]+k-1,w=1;
update(1,1,n);
//update(x[i],x[i]+k-1,1);//2
//update(x[i]+k,y[i],0);
y1=x[i]+k,y2=y[i],w=0;
update(1,1,n);
if (x[i]<=pos&&pos<=y[i]) pos=x[i]+k-1;// 2
}
}
y1=y2=p;
k=0;
query(1,1,n);
if (k==1) l=mid+1;
else r=mid;
}
printf("%d",l-1);
return 0;
}