题目链接 poj3255 Help with Intervals
题目大意:集合的基本操作,具体地说就是并、交、相对补和对称差。五种操作 ‘U
’、‘I
’、‘D
’、‘C
’和‘S
’中的一个 加上一个区间(T),
形式为(
a,
b)
、(
a,
b]
、[
a,
b)
和[
a,
b]。
解题思路: U:把区间[l,r]覆盖成1; I:把区间把[-∞,l)(r,∞]覆盖成0; D:把区间[l,r]覆盖成0。
C:把区间[-∞,l)(r,∞],再对[l,r]区间0/1异或一次。 S:区间[l,r]内0/1异或一次。
这里要注意的一点就是先覆盖再异或 and 先异或再覆盖的区别了,两者是不同的。
#include<cstdio>
#include<iostream>
#include<cstring>
#define lz l,m,rt<<1
#define rz m+1,r,rt<<1|1
using namespace std;
const int mm=133333;
int col[mm<<2],turn[mm<<2],cov[mm+5];
void T(int rt)
{
if(col[rt])col[rt]^=3;
else turn[rt]^=1;
}
void pushdown(int rt)
{
if(col[rt])
{
col[rt<<1]=col[rt<<1|1]=col[rt];
col[rt]=turn[rt<<1]=turn[rt<<1|1]=0;
}
if(turn[rt])
{
T(rt<<1);
T(rt<<1|1);
turn[rt]=0;
}
}
void updata(int L,int R,int op,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
if(op)col[rt]=op,turn[rt]=0;
else T(rt);
return;
}
pushdown(rt);
int m=(l+r)>>1;
if(L<=m)updata(L,R,op,lz);
if(R>m)updata(L,R,op,rz);
}
void query(int l,int r,int rt)
{
if(col[rt])
{
if(col[rt]<2)
for(int i=l; i<=r; ++i)cov[i]=1;
return;
}
if(l==r)return;
pushdown(rt);
int m=(l+r)>>1;
query(lz);
query(rz);
}
int main()
{
char op,l,r;
int i,a,b,flag;
updata(0,mm,2,0,mm,1);
while(~scanf("%c %c%d,%d%c\n",&op,&l,&a,&b,&r))
{
a=(a<<1)+(l=='(');
b=(b<<1)-(r==')');
if(a>b)
{
if(op=='I'||op=='C')updata(0,mm,2,0,mm,1);
}
else
{
if(op=='U')updata(a,b,1,0,mm,1);
if(op=='I'||op=='C')
{
if(a>0)updata(0,a-1,2,0,mm,1);
if(b<mm)updata(b+1,mm,2,0,mm,1);
}
if(op=='D')updata(a,b,2,0,mm,1);
if(op=='C'||op=='S')updata(a,b,0,0,mm,1);
}
}
memset(cov,0,sizeof(cov));
query(0,mm,1);
for(a=b=-1,flag=i=0; i<=mm; ++i)
if(cov[i])b=i,a=a<0?i:a;
else if(a>=0)
{
if(flag)printf(" ");
flag=1;
printf("%c%d,%d%c",a&1?'(':'[',a>>1,(b+1)>>1,b&1?')':']');
a=b=-1;
}
if(!flag)printf("empty set");
puts("");
return 0;
}