BZOJ 3226: [Sdoi2008]校门外的区间

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3226

题意:初始集合S为空。模拟四种集合操作:集合并、交、差、补集并。

思路:区间有开区间闭区间,首先区间左右都乘以2,这样闭区间在偶数位置,开区间在奇数位置。然后就是区间染色颜色反转两个操作。注意区间染色时,若有反转标记则清除;反转时若有染色标记则直接将染色反转即可。

const int N=70005;

struct node
{
	int L,R;
	int re,color;

	void fill(int c)
	{
		if(re) re=0;
		color=c;
	}

	void reverse()
	{
		if(color!=-1) color^=1;
		else
		{
			re^=1;
		}
	}
};

node a[N<<3];

void build(int t,int L,int R)
{
	a[t].L=L;
	a[t].R=R;
	a[t].color=0;
	a[t].re=0;
	if(L==R) return;
	int M=(L+R)>>1;
	build(t<<1,L,M);
	build(t<<1|1,M+1,R);
}

void pushDown(int t)
{
	if(a[t].L==a[t].R) return;
	if(a[t].color!=-1)
	{
		a[t<<1].fill(a[t].color);
		a[t<<1|1].fill(a[t].color);
		a[t].color=-1;
	}
	if(a[t].re)
	{
		a[t<<1].reverse();
		a[t<<1|1].reverse();
		a[t].re=0;
	}
}

void fill(int t,int L,int R,int c)
{
	if(L>R) return;
	if(a[t].L==L&&a[t].R==R)
	{
		a[t].fill(c);
		return;
	}
	pushDown(t);
	int M=(a[t].L+a[t].R)>>1;
	if(R<=M) fill(t<<1,L,R,c);
	else if(L>M) fill(t<<1|1,L,R,c);
	else
	{
		fill(t<<1,L,M,c);
		fill(t<<1|1,M+1,R,c);
	}
}

void rev(int t,int L,int R)
{
	if(L>R) return;
	if(a[t].L==L&&a[t].R==R)
	{
		a[t].reverse();
		return;
	}
	pushDown(t);
	int M=(a[t].L+a[t].R)>>1;
	if(R<=M) rev(t<<1,L,R);
	else if(L>M) rev(t<<1|1,L,R);
	else
	{
		rev(t<<1,L,M);
		rev(t<<1|1,M+1,R);
	}
};

vector<pair<int,int> > V;

void dfs(int t)
{
	if(a[t].color==1)
	{
		V.pb(MP(a[t].L,a[t].R));
		return;
	}

	if(a[t].color==0) return;
	pushDown(t);
	dfs(t<<1);
	dfs(t<<1|1);
}

int main()
{

	int n=N<<1;
	build(1,0,n);
	char op,ll,rr;
	int l,r;
	while(scanf("%c %c%d,%d%c\n",&op,&ll,&l,&r,&rr)!=-1)
	{
		l<<=1;
		r<<=1;
		if(ll=='(') l++;
		if(rr==')') r--;
		if(op=='U') fill(1,l,r,1);
		else if(op=='I') fill(1,0,l-1,0),fill(1,r+1,n,0);
		else if(op=='D') fill(1,l,r,0);
		else if(op=='C') fill(1,0,l-1,0),fill(1,r+1,n,0),rev(1,l,r);
		else rev(1,l,r);
	}
	dfs(1);
	if(SZ(V)==0)
	{
		puts("empty set");
		return 0;
	}
	int i;
	int tot=SZ(V);
	for(i=0;i<tot-1;i++)
	{
		if(V[i].second+1==V[i+1].first) V[i+1].first=V[i].first;
        else
		{
			if(V[i].first&1) putchar('(');
			else putchar('[');
            printf("%d,%d",V[i].first>>1,V[i].second+1>>1);
            if(V[i].second&1) putchar(')');
            else putchar(']');
            putchar(' ');

        }

	}
	if(V[i].first&1) putchar('(');
	else putchar('[');
	printf("%d,%d",V[i].first>>1,V[i].second+1>>1);
    if(V[i].second&1) putchar(')');
    else putchar(']');
    putchar(' ');
	puts("");
}
上一篇:Python day7_set集合的常用方法以及常用格式化的总结


下一篇:css小细节罗列