Time Limit: 6000MS | Memory Limit: 131072K | |
Total Submissions: 11287 | Accepted: 2785 | |
Case Time Limit: 2000MS |
Description
LogLoader是一家专门提供日志分析产品的公司。Ikki在做毕业设计的同时,还忙于在LogLoader做实习。在他的工作里,有一项是要写一个模块来处理时间区间。这个事情一直让他感到很迷糊,所以现在他很需要你帮忙。
在离散数学里面,你已经学习了几种基本的集合运算,具体地说就是并、交、相对补和对称差。它们自然地也适用于区间这种特殊的集合。作为你的快速参考,它们可以总结成下表:
运算 记号 定义
并 A ∪ B {x : x ∈ A或x ∈ B} 交 A ∩ B {x : x ∈ A并x ∈ B} 相对补 A − B {x : x ∈ A但是x ∉B} 对称差 A ⊕ B (A − B) ∪ (B − A)
Ikki已经把他的工作里出现的区间运算抽象成一个很小的编程语言。他想你为他实现一个解析器。这个语言维护一个集合S。S一开始是空集,并根据下列命令被修改:
命令 语义 U
TS ← S ∪ T I
TS ← S ∩ T D
TS ← S − T C
TS ← T − S S
TS ← S ⊕ T
Input
输入包含一组测试数据,由0到65,535条命令组成。每条命令占一行,形式如下:
X
T
其中X
是‘U
’、‘I
’、‘D
’、‘C
’和‘S
’中的一个,T是一个区间,
形式为(
a,
b)
、(
a,
b]
、[
a,
b)
和[
a,
b]
之一(a, b ∈ Z; 0 ≤ a ≤ b ≤ 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);
}