[BZOJ] 4552: [Tjoi2016&Heoi2016]排序

通过各种手段把序列问题变成01序列问题可以简化问题

这里可以用二分答案,把大于等于的变成1,小于的变成0

然后区间排序就是线段树区间赋值操作啦

复杂度\(O(nlog^2n)\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

inline int rd(){
	int ret=0,f=1;char c;
	while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
	while(isdigit(c))ret=ret*10+c-'0',c=getchar();
	return ret*f;
}
#define pc putchar
#define space() pc(' ')
#define nextline() pc('\n')
void pot(int x){if(!x)return;pot(x/10);pc('0'+x%10);}
void out(int x){if(!x)pc('0');if(x<0)pc('-'),x=-x;pot(x);}

#define ls (cur<<1)
#define rs (cur<<1|1)
#define mid (((l)+(r))>>1)

const int MAXN = 100005;

int val[MAXN<<2],tag[MAXN<<2];

int n,m;
int a[MAXN];
int M;

void pushdown(int cur,int l,int r){
	if(tag[cur]==-1) return;
	if(l==r) return;
	val[ls]=(mid-l+1)*tag[cur];
	val[rs]=(r-mid)*tag[cur];
	tag[ls]=tag[cur];
	tag[rs]=tag[cur];
	tag[cur]=-1;
}

void pushup(int cur){val[cur]=val[ls]+val[rs];}

void build(int cur,int l,int r){
	if(l==r){val[cur]=(a[l]>=M);return;}
	build(ls,l,mid);build(rs,mid+1,r);
	pushup(cur);
}

void update(int L,int R,int cur,int l,int r,int w){
	if(L>R) return;
	if(L<=l&&r<=R){tag[cur]=w;val[cur]=w*(r-l+1);return;}
	pushdown(cur,l,r);
	if(L<=mid) update(L,R,ls,l,mid,w);
	if(mid <R) update(L,R,rs,mid+1,r,w);
	pushup(cur);
}

int query1(int L,int R,int cur,int l,int r){
	if(L<=l&&r<=R){return val[cur];}
	pushdown(cur,l,r);
	int ret=0;
	if(L<=mid) ret+=query1(L,R,ls,l,mid);
	if(mid <R) ret+=query1(L,R,rs,mid+1,r);
	return ret;	
}
struct Qry{
	int op,x,y;	
	Qry(int _x=0,int _y=0,int _z=0){op=_x;x=_y;y=_z;}
}qry[MAXN];

void clear(){
	memset(tag,-1,sizeof(tag));
	memset(val,0,sizeof(val));
}
	
int p;
bool check(){
	clear();	
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int x=qry[i].x,y=qry[i].y;
		if(qry[i].op==1){
			int tmp=query1(x,y,1,1,n);
			update(x,x+tmp-1,1,1,n,1);
			update(x+tmp,y,1,1,n,0);
		}else{
			int tmp=y-x+1-query1(x,y,1,1,n);
			update(x,x+tmp-1,1,1,n,0);
			update(x+tmp,y,1,1,n,1);
		}
	}	
	return query1(p,p,1,1,n);
}	


int main(){
	n=rd();m=rd();
	for(int i=1;i<=n;i++) a[i]=rd();
	int tp,x,y;
	for(int i=1;i<=m;i++){
		tp=rd();x=rd();y=rd();
		qry[i]=Qry(tp,x,y);
	}
	p=rd();
	int l=1,r=n,ans=0;
	while(l<=r){
		M=(l+r)>>1;
		if(check()) l=M+1,ans=M;
		else r=M-1;
	}
	cout<<ans;
	return 0;
}
posted @ 2018-11-02 22:28  GhostCai  阅读(171)  评论(0编辑  收藏  举报