[BZOJ4552][Tjoi2016&Heoi2016]排序(二分答案+线段树)

二分答案mid,将>=mid的设为1,<mid的设为0,这样排序就变成了区间修改的操作,维护一下区间和即可

然后询问第q个位置的值,为1说明>=mid,以上

时间复杂度O(nlog2n)

tips: 线段树操作区间[l,r]需满足l<=r,要特判;tag可能为0,要初始化为-1

Code

#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 100010
using namespace std;

struct info{int x,l,r;}q[N];
int n,m,A[N],f[N],Ans,Q;

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

namespace Seg{
	#define MID int mid=(l+r)>>1,ls=id<<1,rs=id<<1|1
	int tag[N*4];
	struct tree{int c[2];}T[N*4];
	void pushup(int l,int r,int id){
		MID;
		T[id].c[0]=T[ls].c[0]+T[rs].c[0];
		T[id].c[1]=T[ls].c[1]+T[rs].c[1];
	}
	void pushdown(int l,int r,int id){
		int &tmp=tag[id];
		if(tmp==-1)return;
		MID;
		tag[ls]=tag[rs]=tmp;
		T[ls].c[tmp]=mid-l+1,T[ls].c[tmp^1]=0;
		T[rs].c[tmp]=r-mid,T[rs].c[tmp^1]=0;
		tmp=-1;
	}
	void build(int l,int r,int id){
		if(l==r){
			T[id].c[0]=(f[l]==0)?1:0;
			T[id].c[1]=T[id].c[0]^1;
			return;
		}
		MID;
		build(l,mid,ls),build(mid+1,r,rs);
		pushup(l,r,id);
	}
	int query(int l,int r,int id,int L,int R,int x){
		if(L<=l&&r<=R)return T[id].c[x];
		pushdown(l,r,id);
		MID;
		int res=0;
		if(L<=mid)res+=query(l,mid,ls,L,R,x);
		if(R>mid)res+=query(mid+1,r,rs,L,R,x);
		return res;
	}
	void upd(int l,int r,int id,int L,int R,int x){
		if(L<=l&&r<=R){
			tag[id]=x;
			T[id].c[x]=r-l+1,T[id].c[x^1]=0;
			return;
		}
		pushdown(l,r,id);
		MID;
		if(L<=mid)upd(l,mid,ls,L,R,x);
		if(R>mid)upd(mid+1,r,rs,L,R,x);
		pushup(l,r,id);
	}
	void clr(){memset(tag,-1,sizeof(tag));}
}using namespace Seg;

int main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)A[i]=read();
	for(int i=1;i<=m;++i)q[i].x=read(),q[i].l=read(),q[i].r=read();
	Q=read();
	for(int l=1,r=n;l<=r;){
		int mid=(l+r)>>1;
		for(int i=1;i<=n;++i)f[i]=(A[i]>=mid)?1:0;
		clr(),build(1,n,1);
		for(int i=1;i<=m;++i){
			int L=q[i].l,R=q[i].r,x=q[i].x;
			int cnt=query(1,n,1,L,R,x);
			if(cnt)upd(1,n,1,L,L+cnt-1,x);
			if(cnt<(R-L+1))upd(1,n,1,L+cnt,R,x^1);
		}
		if(query(1,n,1,Q,Q,1)==1) Ans=mid,l=mid+1;
		else r=mid-1;
	}
	printf("%d\n",Ans);
	return 0;
}

 

posted @ 2018-07-27 16:53  void_f  阅读(164)  评论(0编辑  收藏  举报