POJ 题目3225 区间(线段树区间交并差,区间异或)

区间
Time Limit: 6000MS Memory Limit: 131072K
Total Submissions: 11287 Accepted: 2785
Case Time Limit: 2000MS

Description

LogLoader是一家专门提供日志分析产品的公司。Ikki在做毕业设计的同时,还忙于在LogLoader做实习。在他的工作里,有一项是要写一个模块来处理时间区间。这个事情一直让他感到很迷糊,所以现在他很需要你帮忙。

在离散数学里面,你已经学习了几种基本的集合运算,具体地说就是并、交、相对补和对称差。它们自然地也适用于区间这种特殊的集合。作为你的快速参考,它们可以总结成下表:

运算记号

定义

AB{x : xAxB}
AB{x : xAxB}
相对补AB{x : xA但是xB}
对称差AB(AB) ∪ (BA)

Ikki已经把他的工作里出现的区间运算抽象成一个很小的编程语言。他想你为他实现一个解析器。这个语言维护一个集合SS一开始是空集,并根据下列命令被修改:

命令语义
U TSST
I TSST
D TSST
C TSTS
S TSST

Input

输入包含一组测试数据,由0到65,535条命令组成。每条命令占一行,形式如下:

X T

其中X是‘U’、‘I’、‘D’、‘C’和‘S’中的一个,T是一个区间形式为(a,b)(a,b][a,b)[a,b]之一(a, bZ; 0 ≤ ab ≤ 65,535),取它们通常的意义。命令按在输入中出现的顺序执行。

文件结束符(EOF)表示输入结束。

Output

以一组不相交区间的并的形式输出在最后一条命令执行之后的集合S。这些区间在一行内输出,由单个空格分隔,按端点的升序排序。如果S是空集,输出“empty set”。

Sample Input

U [1,5]
D [3,3]
S [2,4]
C (1,5)
I (2,3]

Sample Output

(2,3)

Source

Translator

Yingchong SITU 'frkstyc'

思路:

我们一个一个操作来分析:(用0和1表示是否包含区间,-1表示该区间内既有包含又有不包含)

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记录,有三种状态,-1,0,1,分别表示区间是否被覆盖,全覆盖为0,全覆盖为1。

异或操作的话,Xor来记录改区间是否被异或过,向下传递异或。

覆盖操作:

把异或标记设置为0,因为覆盖了之后,以前的异或操作就可以不用进行。

异或操作:

如果有覆盖操作,直接把覆盖异或就行了,把异或操作置0

否则,将异或标志与1异或。

ac代码

Problem: 3225  User: kxh1995 
Memory: 2824K  Time: 938MS 
Language: C++  Result: Accepted 
#include<stdio.h>
#include<string.h>
#define maxn 65555<<1
struct s
{
	int cover,Xor;
}node[65555<<4];
int hash[65555<<4];
void fxor(int tr)
{
	if(node[tr].cover!=-1)
		node[tr].cover^=1;
	else
		node[tr].Xor^=1;
}
void pushdown(int tr)
{
	if(node[tr].cover!=-1)
	{
		node[tr<<1].cover=node[tr<<1|1].cover=node[tr].cover;
		node[tr<<1].Xor=node[tr<<1|1].Xor=0;
		node[tr].cover=-1;
	}
	if(node[tr].Xor)
	{
		fxor(tr<<1);
		fxor(tr<<1|1);
		node[tr].Xor=0;
	}
}
void update(char op,int L,int R,int l,int r,int tr)
{
	if(L<=l&&r<=R)
	{
		if(op=='U')
		{
			node[tr].cover=1;
			node[tr].Xor=0;
		}
		else
			if(op=='D')
			{
				node[tr].cover=0;
				node[tr].Xor=0;
			}
			else
				if(op=='C'||op=='S')
					fxor(tr);
				return;
	}
	pushdown(tr);
	int mid=(l+r)>>1;
	if(L<=mid)
	{
		update(op,L,R,l,mid,tr<<1);
	}
	else
	{
		if(op=='I'||op=='C')
			node[tr<<1].Xor=node[tr<<1].cover=0;
	}
	if(mid<R)
	{
		update(op,L,R,mid+1,r,tr<<1|1);
	}
	else
	{
		if(op=='I'||op=='C')
			node[tr<<1|1].Xor=node[tr<<1|1].cover=0;
	}
}
void query(int l,int r,int tr)
{
	if(node[tr].cover==1)
	{
		for(int i=l;i<=r;i++)
			hash[i]=1;
		return;
	}
	else
		if(node[tr].cover==0)
			return;
		if(l==r)
			return;
		pushdown(tr);
		int mid=(l+r)>>1;
		query(l,mid,tr<<1);
		query(mid+1,r,tr<<1|1);
}
int main()
{
	node[1].cover=node[1].Xor=0;
	char op,a,b;
	int x,y;
	while(scanf("%c %c%d,%d%c",&op,&a,&x,&y,&b)!=EOF)
	{
		getchar();
		x<<=1;
		y<<=1;
		if(a=='(')
			x++;
		if(b==')')
			y--;
		if(x>y)
		{
			continue;
		}
		update(op,x,y,0,maxn,1);
	}
	query(0,maxn,1);
	int s=-1,t,flag=0;
	for(int i=0;i<=maxn;i++)
	{
		if(hash[i])
		{
			if(s==-1)
				s=i;
			t=i;
		}
		else
		{
			if(s!=-1)
			{
				if(flag==1)
					printf(" ");
				flag=1;
				if(s&1)
					a='(';
				else
					a='[';
				if(t&1)
					b=')';
				else
					b=']';
				printf("%c%d,%d%c",a,s>>1,(t+1)>>1,b);
					s=-1;
			}
		}
	}
	if(flag==0)
		printf("empty set\n");
	printf("\n");
	//while(1);
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值