POJ 3225 区间操作 交并补

U:把区间[l,r]覆盖成1
I:把[-∞,l)(r,∞]覆盖成0
D:把区间[l,r]覆盖成0
C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换
S:[l,r]区间0/1互换

 

cover记录成段覆盖,xo记录互换

当一个节点得到覆盖标记时把异或标记清空
当一个节点得到异或标记的时候,先判断覆盖标记,如果是0或1,直接改变一下覆盖标记,不然的话改变异或标记

开区间闭区间只要数字乘以2就可以处理(偶数表示端点,奇数表示两端点间的区间)
例: [2,3]=4->6      (2,3)=5->5   [2,3)=4->5 

最后用hash查找一下即可

注意边界判断

PS:翻译了半天才发现题目竟然可以选择中文.........

 

#include "stdio.h"
#include "string.h"
#include "math.h"
#include "stdlib.h"
#include "iostream"
#include "algorithm"
using namespace std;

struct comp
{
	int num1,num2;
	char l,r,op;
} sca[300010];

struct comp1
{
	int l,r,cover,mid,xo,x;
} data[300010];

int first;
int hash[300010];

void Pushdown(int k)
{
	if (data[k].l==data[k].r) return ;

	if (data[k].cover!=-1)
	{
		data[k*2].cover=data[k*2+1].cover=data[k].cover;

		data[k*2].xo=data[k*2+1].xo=0;

		data[k*2].x=data[k*2+1].x=data[k].cover;

		data[k].cover=-1;
		return ;
	}

	if (data[k].xo%2!=0)
	{
		if (data[k*2].cover==1) data[k*2].cover=0;  //  覆盖标记不为-1时,直接改变覆盖标记
		else 
			if (data[k*2].cover==0) data[k*2].cover=1;
				else data[k*2].xo++;

		if (data[k*2+1].cover==0) data[k*2+1].cover=1; 
		else 
			if (data[k*2+1].cover==1) data[k*2+1].cover=0;
				else data[k*2+1].xo++;

		if (data[k*2].x==1)
			data[k*2].x=0;
		else 
			if (data[k*2].x==0) 
				data[k*2].x=1;

		if (data[k*2+1].x==1)
			data[k*2+1].x=0;
		else 
			if (data[k*2+1].x==0)
				data[k*2+1].x=1;

		data[k].xo=0;
	}
}


void build(int l,int r,int k)
{
	data[k].l=l;
	data[k].r=r;
	data[k].mid=(l+r)/2;
	data[k].cover=-1;
	data[k].xo=0;
	data[k].x=0;

	if (l==r) return ;

	build(l,data[k].mid,k*2);
	build(data[k].mid+1,r,k*2+1);
}


void update_cover(int l,int r,int k,int op)
{
	if (data[k].l==l && data[k].r==r)
	{
		data[k].cover=op;
		data[k].x=op;
		data[k].xo=0;
		return ;
	}

	Pushdown(k);

	if (r<=data[k].mid) update_cover(l,r,k*2,op);
	else 
		if (l>data[k].mid) update_cover(l,r,k*2+1,op);
		else 
		{
			update_cover(l,data[k].mid,k*2,op);
			update_cover(data[k].mid+1,r,k*2+1,op);
		}

	if (data[k*2].x==data[k*2+1].x && data[k*2].x!=-1) data[k].x=data[k*2].x; else data[k].x=-1;
}

void update_xor(int l,int r,int k)
{
	if (data[k].l==l && data[k].r==r)
	{
		
		if (data[k].x==0) data[k].x=1;
		else 
			if (data[k].x==1) data[k].x=0;

		if (data[k].cover==0) data[k].cover=1 ; //  覆盖标记不为-1时,直接改变覆盖标记
		else 
			if (data[k].cover==1) data[k].cover=0;
			else data[k].xo++;
	
		return ;
	}

	Pushdown(k);

	if (r<=data[k].mid) update_xor(l,r,k*2);
	else 
		if (l>data[k].mid) update_xor(l,r,k*2+1);
		else 
		{
			update_xor(l,data[k].mid,k*2);
			update_xor(data[k].mid+1,r,k*2+1);
		}

	if (data[k*2].x==data[k*2+1].x && data[k*2].x!=-1) data[k].x=data[k*2].x; else data[k].x=-1;
}

void search(int k)
{
	int i;
	
	if (data[k].x==1)
	{
		first=0;
		for (i=data[k].l;i<=data[k].r;i++)
			hash[i]=1;

		return ;
	}
	else 
		if (data[k].x==0) return ;
		else 
		{
			Pushdown(k);
			search(k*2);
			search(k*2+1);
		}
}

int main()
{
	int s,e,n,a,b,i,m;
	char ch[10];

	n=0;
	m=0;
	
	while (scanf("%s",ch)!=EOF)
	{
		getchar();
		n++;
		sca[n].op=ch[0];
		scanf("%c%d,%d%c\n",&sca[n].l,&sca[n].num1,&sca[n].num2,&sca[n].r);

		if (sca[n].num1>m) m=sca[n].num1;
		if (sca[n].num2>m) m=sca[n].num2;
		
	}

	build(0,m*2,1);

	for (i=1;i<=n;i++)
	{
		a=sca[i].num1*2;
		b=sca[i].num2*2;
		if (sca[i].l=='(') a++;
		if (sca[i].r==')') b--;

		if (sca[i].op=='U') 
		{		
			if (a<=b) update_cover(a,b,1,1);
		}

		if (sca[i].op=='I')
		{
			if (a<=b)
			{		
				if (a!=0) update_cover(0,a-1,1,0);
			
				if (b!=m*2) update_cover(b+1,m*2,1,0);
			}
			else update_cover(0,m*2,1,0);
		}

		if (sca[i].op=='D')
		{
			if (a<=b)
			update_cover(a,b,1,0);
		}

		if (sca[i].op=='C')
		{
			if (a<=b)
			{
				update_xor(a,b,1);
			
				if (a!=0) update_cover(0,a-1,1,0);
			
				if (b!=m*2) update_cover(b+1,m*2,1,0);
			}
			else update_cover(0,m*2,1,0);
		}

		if (sca[i].op=='S') 
		{
			if (a<=b) update_xor(a,b,1);
		}


	}
	first=1;
	memset(hash,0,sizeof(hash));
	search(1);

	if (first==1) printf("empty set");
	else 
	{
		s=-1;
		for (i=0;i<=m*2;i++)
			if (hash[i]==1)
			{
				if (s==-1)  s=i;
				e=i;
			}
			else 
				if (s!=-1)
				{
					if (first==1) printf(" ");else first=1;

				    if (s%2==0) printf("["); else printf("(");
					printf("%d,",s/2); 
					if (e%2==0) printf("%d]",e/2); else printf("%d)",e/2+1);
						
					s=-1;
				}

		if (s!=-1)
				{
					if (first==1) printf(" ");else first=1;

				    if (s%2==0) printf("["); else printf("(");
					printf("%d,",s/2); 
					if (e%2==0) printf("%d]",e/2); else printf("%d)",e/2+1);
							
					s=-1;
				}
	
	}
}


 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值