BZOJ 4552 [Tjoi2016&Heoi2016]排序

题解:二分一个答案,<=mid设成0,>mid设成1

然后验证,每次排序相当于把两(一)段区间赋成0和1

#include<iostream>
#include<cstdio>
#include<cstring>
#define lo now<<1
#define ro now<<1|1
using namespace std;
const int maxn=200009;

int n,T,p;
int opty[maxn],opl[maxn],opr[maxn];
int a[maxn];
int b[maxn];

int l,r,mid,ans;

struct SegmentTree{
	int l,r;
	int st;
	int sum0;
}tree[maxn<<2];
void pushup(int now){
	tree[now].sum0=tree[lo].sum0+tree[ro].sum0;
}
void Puttag(int now,int st){
	if(st==-1)return;
	tree[now].st=st;
	int l=tree[now].l,r=tree[now].r;
	if(st==0)tree[now].sum0=r-l+1;
	else tree[now].sum0=0;
}

void pushdown(int now){
	Puttag(lo,tree[now].st);
	Puttag(ro,tree[now].st);
	tree[now].st=-1;
}

void BuildTree(int now,int l,int r){
	tree[now].l=l;tree[now].r=r;tree[now].st=-1;
	if(l==r){
		tree[now].sum0=1-b[l];
		return;
	}
	int mid=(l+r)>>1;
	BuildTree(lo,l,mid);
	BuildTree(ro,mid+1,r);
	pushup(now);
}

void Updatasec(int now,int ll,int rr,int st){
	if(tree[now].l>=ll&&tree[now].r<=rr){
		Puttag(now,st);
		return;
	}
	pushdown(now);
	int mid=(tree[now].l+tree[now].r)>>1;
	if(ll<=mid)Updatasec(lo,ll,rr,st);
	if(rr>mid)Updatasec(ro,ll,rr,st);
	pushup(now);
}

int Querysum(int now,int ll,int rr){
	if(tree[now].l>=ll&&tree[now].r<=rr){
		return tree[now].sum0;
	}
	pushdown(now);
	int mid=(tree[now].l+tree[now].r)>>1;
	int ret=0;
	if(ll<=mid)ret+=Querysum(lo,ll,rr);
	if(rr>mid)ret+=Querysum(ro,ll,rr);
	return ret;
}

int main(){
	scanf("%d%d",&n,&T);
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	for(int i=1;i<=T;++i)scanf("%d%d%d",&opty[i],&opl[i],&opr[i]);
	scanf("%d",&p);
	
	l=1;r=n;
	while(l<=r){
		mid=(l+r)>>1;
		for(int i=1;i<=n;++i){
			if(a[i]<=mid)b[i]=0;
			else b[i]=1;
		}
		BuildTree(1,1,n);
		for(int i=1;i<=T;++i){
			int sum=Querysum(1,opl[i],opr[i]);
			if(opty[i]==0){
				Updatasec(1,opl[i],opl[i]+sum-1,0);
				Updatasec(1,opl[i]+sum,opr[i],1);
			}else{
				sum=opr[i]-opl[i]+1-sum;
				Updatasec(1,opl[i],opl[i]+sum-1,1);
				Updatasec(1,opl[i]+sum,opr[i],0);
			}
		}
		int fin=1-Querysum(1,p,p);
		if(fin==0){
			ans=mid;
			r=mid-1;
		}else{
			l=mid+1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

  

posted @ 2018-03-08 21:41  ws_zzy  阅读(131)  评论(0编辑  收藏  举报