POJ 3225 Help with Intervals
题目链接:POJ 3225
题意:
S一开始是空集,然后进行5个操作。
U a b 是将区间[a,b]变成1.
I a b 是将(-oo,a)(b,+oo)变成0.
D a b 是将区间[a,b]变成0.
C a b 是将(-oo,a)(b,+oo)变成0且[a,b]进行异或操作。
S a b 是将区间[a,b]异或操作.
以一组不相交区间的并的形式输出在最后一条命令执行之后的集合S。这些区间在一行内输出,由单个空格分隔,按端点的升序排序。
如果S是空集,输出“empty set
”。
分析:
对线段区间进行0,1标记表示该区间是否包含在s内。
是否覆盖0,1是否转换0,1的0,1转换都可以用异或去转换
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long LL;
const int maxn = 131072;
int k, tn, tcase = 0;
bool Hash[maxn];
//cover表示区间的0,1状态,XOR表示该区间转换的状态
int XOR[maxn<<2],cover[maxn<<2];
void pushup(int rt)
{
//表示整个区间可以同时转换
if(cover[rt]!=-1)
cover[rt]^=1;
else
XOR[rt]^=1;
}
void pushdown(int rt)
{
if(cover[rt]!=-1)
{
cover[rt<<1]=cover[rt<<1|1]=cover[rt];
XOR[rt<<1]=XOR[rt<<1|1]=0;
cover[rt]=-1;;
}
//表示该点转换了但是孩子未转换
if(XOR[rt])
{
pushup(rt<<1);
pushup(rt<<1|1);
XOR[rt]=0;
}
}
void update(char op,int L, int R,int l, int r, int rt)
{
if (L <= l && R>= r) // L<=l<=r<=R
{
if(op=='U')
cover[rt]=1,XOR[rt]=0;
else if(op=='D')
cover[rt]=0,XOR[rt]=0;
else if(op=='C'||op=='S')
pushup(rt);
return ;
}
pushdown(rt);
int mid = (l + r) >> 1;
if (L <= mid)
update(op,L, R, lson);
else if(op=='I'||op=='C')
cover[rt<<1]=XOR[rt<<1]=0;
if (R > mid)
update(op,L, R, rson);
else if(op=='I'||op=='C')
cover[rt<<1|1]=XOR[rt<<1|1]=0;
}
void query(int l, int r, int rt)
{
if(cover[rt]==1)
{
for(int i=l;i<=r;i++)
Hash[i]=true;
return ;
}
if(cover[rt]==0)
return ;
if(l==r)
return ;
pushdown(rt);
int mid = (l + r) >> 1;
query(lson);
query(rson);
}
int main()
{
// freopen("in.txt","r",stdin);
char op,l,r;
int a,b;
while(scanf("%c %c%d,%d%c",&op,&l,&a,&b,&r)!=EOF)
{
a<<=1;b<<=1;
if(l=='(')
a++;
if(r==')')
b--;
if(a>b) //比如输入区间为I (1,1)或C (1,1)
{
if(op=='C'||op=='I')//将-oo~l,r~+oo标记为0
{
cover[1]=XOR[1]=0;
}
}
else
update(op,a,b,0,maxn,1);
getchar();
}
query(0,maxn,1);
int ok=0,s=-1,e;
for(int i=0;i<maxn;i++)
{
if(Hash[i])
{
if(s==-1)
s=i;
e=i;
}
else
{
if(s!=-1)
{
if(ok)
printf(" ");
else
ok=1;
printf("%c%d,%d%c",s&1?'(':'[',s>>1,(e+1)>>1,
e&1?')':']');
s=-1;
}
}
}
if(!ok)
printf("empty set");
printf("\n");
return 0;
}