BZOJ3226: [Sdoi2008]校门外的区间

感觉很有趣的题呢。

每个点拆成两个,线段树维护。

不过这题难点其实在输入输出。

#include<bits/stdc++.h>
#define N (65535<<1)
#define M (l+r>>1)
#define P (k<<1)
#define S (k<<1|1)
#define K l,r,k
#define L l,M,P
#define R M+1,r,S
#define Z \
int l=0,int r=N,int k=1
int u[1<<18],v[1<<18],a[N+10];
template<int d>
void same(int k){
	u[k]=d;
	v[k]=0;
}
void flip(int k){
	(~u[k]?u[k]:v[k])^=1;
}
void (*operate[3])(int)
={same<0>,same<1>,flip};
void devolve(int k){
	int d=v[k]?2:u[k];
	if(~d){
		operate[d](P);
		operate[d](S);
		v[k]=0;
		u[k]=-1;
	}
}
void A(int d,int s,int t,Z){
	if(s==l&&t==r)
		operate[d](k);
	else{
		devolve(k);
		if(t<=M)
			A(d,s,t,L);
		else if(s>M)
			A(d,s,t,R);
		else{
			A(d,s,M,L);
			A(d,M+1,t,R);
		}
	}
}
void finish(Z){
	if(~u[k])
		for(int i=l;i<=r;++i)
			a[i]=u[k];
	else{
		devolve(k);
		finish(L);
		finish(R);
	}
}
bool empty(){
	for(int i=0;i<=N;++i)
		if(a[i])
			return 0;
	return 1;
}
int main(){
	memset(u,-1,sizeof u);
	char d[2],b[16];
	while(~scanf("%s%s",d,b)){
		char u,v;
		int s,t;
		sscanf(b,"%c%d,%d%c",&u,&s,&t,&v);
		s=s*2+(u=='(');
		t=t*2-(v==')');
		if(s>t)
			continue;
		switch(*d){
		case'D':
			A(0,s,t);
			break;
		case'U':
			A(1,s,t);
			break;
		case'S':
			A(2,s,t);
			break;
		default:
			if(s)
				A(0,0,s-1);
			if(t!=N)
				A(0,t+1,N);
			if(*d=='C')
				A(2,s,t);
		}
	}
	finish();
	if(empty())
		puts("empty set");
	else
		for(int i=0;i<=N;++i){
			if((!i||!a[i-1])&&a[i])
				printf("%c%d,",i&1?'(':'[',i>>1);
			if(a[i]&&!a[i+1])
				printf("%d%c ",i+1>>1,i&1?')':']');
		}
}
posted @ 2016-05-15 20:48  f321dd  阅读(133)  评论(0编辑  收藏  举报