码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3226: [Sdoi2008]校门外的区间 线段树

时间:2016-05-15 21:32:47      阅读:382      评论:0      收藏:0      [点我收藏+]

标签:

题比较有趣,输入输出比较麻烦。

每个点拆成两个,线段树维护。(这题难点真的在输入输出)

#include<bits/stdc++.h>
#define N (1<<17)
#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[N<<2],v[N<<2],a[N<<2];
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;
		if(*d^‘I‘&&*d^‘C‘)
			A(*d==‘S‘
			?2:*d==‘U‘,s,t);
		else{
			if(*d^‘I‘)
				A(2,s,t);
			if(s^0)
				A(0,0,s-1);
			if(t^N)
				A(0,t+1,N);
		}
	}
	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?‘)‘:‘]‘);
		}
}

  

bzoj3226: [Sdoi2008]校门外的区间 线段树

标签:

原文地址:http://www.cnblogs.com/f321dd/p/5496069.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!