1. 程式人生 > >[CF817F]MEX Queries

[CF817F]MEX Queries

sca stdio.h esp long ret class span clas div

題意:三種操作:區間置$0$,區間置$1$,區間取反,每次操作後輸出MEX

直接離散化$l,r,r+1$,用線段樹維護,pushdown的時候先處理覆蓋標記再處理翻轉標記

大套路?

#include<stdio.h>
#include<map>
using namespace std;
#define ll long long
struct ask{
	int op;
	ll l,r;
}q[100010];
map<ll,int>pos;
map<ll,int>::iterator it;
int sum[1200010],rst[1200010],rev[1200010];
ll rpos[300010];
void pushdown(int x,int ln,int rn){
	if(rst[x]){
		sum[x<<1]=ln*(rst[x]-1);
		rst[x<<1]=rst[x];
		sum[x<<1|1]=rn*(rst[x]-1);
		rst[x<<1|1]=rst[x];
		rst[x]=0;
		rev[x<<1]=rev[x<<1|1]=0;
	}
	if(rev[x]){
		sum[x<<1]=ln-sum[x<<1];
		rev[x<<1]^=1;
		sum[x<<1|1]=rn-sum[x<<1|1];
		rev[x<<1|1]^=1;
		rev[x]=0;
	}
}
void pushup(int x){
	sum[x]=sum[x<<1]+sum[x<<1|1];
}
void reset(int L,int R,int v,int l,int r,int x){
	if(L<=l&&r<=R){
		rst[x]=v+1;
		sum[x]=v*(r-l+1);
		rev[x]=0;
		return;
	}
	int mid=(l+r)>>1;
	pushdown(x,mid-l+1,r-mid);
	if(L<=mid)reset(L,R,v,l,mid,x<<1);
	if(mid<R)reset(L,R,v,mid+1,r,x<<1|1);
	pushup(x);
}
void reverse(int L,int R,int l,int r,int x){
	if(L<=l&&r<=R){
		rev[x]^=1;
		sum[x]=r-l+1-sum[x];
		return;
	}
	int mid=(l+r)>>1;
	pushdown(x,mid-l+1,r-mid);
	if(L<=mid)reverse(L,R,l,mid,x<<1);
	if(mid<R)reverse(L,R,mid+1,r,x<<1|1);
	pushup(x);
}
ll query(int l,int r,int x){
	if(l==r)return rpos[l];
	int mid=(l+r)>>1;
	pushdown(x,mid-l+1,r-mid);
	if(sum[x<<1]<mid-l+1)return query(l,mid,x<<1);
	return query(mid+1,r,x<<1|1);
}
int main(){
	int n,m,i;
	scanf("%d",&m);
	pos[1]=1;
	for(i=1;i<=m;i++){
		scanf("%d%I64d%I64d",&q[i].op,&q[i].l,&q[i].r);
		pos[q[i].l]=pos[q[i].r]=pos[q[i].r+1]=1;
	}
	for(n=1,it=pos.begin();it!=pos.end();n++,it++){
		it->second=n;
		rpos[n]=it->first;
	}
	for(i=1;i<=m;i++){
		if(q[i].op==3)
			reverse(pos[q[i].l],pos[q[i].r],1,n,1);
		else
			reset(pos[q[i].l],pos[q[i].r],2-q[i].op,1,n,1);
		printf("%I64d\n",query(1,n,1));
	}
}

[CF817F]MEX Queries