这题思路很巧妙啊
关键点是能够想到对一个01序列的排序可以用log级别的线段树来操作
想到这点后,我们可以二分q位置上的数字,将原序列大于等于这个值的数字都写成1,其他的写成0,然后用线段树模拟排序就行
能够这样做的原因:假设我们二分的值是mid,这里的数字本来是x,那么当x>mid时,最后排序后的q处的数就等于1,反之等于0
实现的时候注意初始化和lazy函数的初值
#include
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define ll long long
#define isdegit(r) ((r>='0'&&r<='9'))
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(!isdegit(r)){if(r==45)neg=-1;r=getchar();}
while(isdegit(r)){x=(x<<1)+(x<<3)+r-48;r=getchar();}
x*=neg;
}
int n,m;
const int maxn=1e5+10,maxm=1e5+10;
int a[maxn];
struct _operator{
int dir,l,r;
_operator(int dir=0,int l=0,int r=0):dir(dir),l(l),r(r){}
}op[maxm];
int sum[maxn<<2],lazy[maxn<<2];
inline void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
inline void pushdown(int l,int r,int rt){
if(lazy[rt]!=-1){
lazy[rt<<1]=lazy[rt];
lazy[rt<<1|1]=lazy[rt];
int mid=(l+r)>>1;
sum[rt<<1]=lazy[rt]*(mid-l+1);
sum[rt<<1|1]=lazy[rt]*(r-(mid+1)+1);
lazy[rt]=-1;
}
}
void buildtree(int l,int r,int rt,int q){
sum[rt]=0;lazy[rt]=-1;
if(l>r)return;
if(l==r){
sum[rt]=(a[l]>=q);
return;
}
int mid=(l+r)>>1;
buildtree(l,mid,rt<<1,q);
buildtree(mid+1,r,rt<<1|1,q);
pushup(rt);
}
int querysum(int l,int r,int nl,int nr,int rt){
if(l>r||nl>nr)return 0;
if(l<=nl&&nr<=r)return sum[rt];
int mid=(nl+nr)>>1;
int res=0;
pushdown(nl,nr,rt);
if(mid>=l)res+=querysum(l,r,nl,mid,rt<<1);
if(mid<r)res+=querysum(l,r,mid+1,nr,rt<<1|1);
return res;
}
void update(int l,int r,int nl,int nr,int rt,int w){
if(l>r||nl>nr)return;
if(l<=nl&&nr<=r){
lazy[rt]=w;
sum[rt]=w*(nr-nl+1);
return;
}
int mid=(nl+nr)>>1;
pushdown(nl,nr,rt);
if(mid>=l)update(l,r,nl,mid,rt<<1,w);
if(mid<r)update(l,r,mid+1,nr,rt<<1|1,w);
pushup(rt);
}
inline bool check(int mid,int q){
buildtree(1,n,1,mid);
loop(i,1,m){
int k=querysum(op[i].l,op[i].r,1,n,1);
if(op[i].dir==0)
update(op[i].r-k+1,op[i].r,1,n,1,1),
update(op[i].l,op[i].r-k,1,n,1,0);
else if(op[i].dir==1)
update(op[i].l+k,op[i].r,1,n,1,0),
update(op[i].l,op[i].l+k-1,1,n,1,1);
}
return querysum(q,q,1,n,1)==1;
}
inline void bin(int q){
int l,r,res;l=1,r=n;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid,q)){
res=mid;
l=mid+1;
}
else r=mid-1;
}
printf("%d\n",res);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif
read(n),read(m);
loop(i,1,n)read(a[i]);
loop(i,1,m){
int ops,l,r;
read(ops),read(l),read(r);
op[i]=_operator(ops,l,r);
}
int q;read(q);
bin(q);
return 0;
}