题意:
先给你一个空区间S, 然后给你很多个区间,将S与这些区间进行交,并,补等操作
方法:
1. 现将集合操作变换为区间更新操作
U: 把区间[L, R]变为1
I; 把区间[0, L,) , [R,∞)变为 0
D: 把区间[L, R]变为0
C:把区间(-∞,L),(R,∞)异或1
S: 对区间[L,R]异或1
2. HH专题上面说倍增区间就可以解决开闭区间的问题, 这里我一直想了很久很久, 我一直以为是2 倍增为4,5之后4表示2的闭,5表示2的开
但是这样在更新的时候会有问题。。 例如区间【1,2】变为1 倍增区间的变化为2,3,4为1, 2 的闭 并不为1
直到我看到:
http://my.oschina.net/llmm/blog/124256
才明白原来倍增区间是这样使用的
如[2,3]倍增为[4,6], 其中[2,3)可用[4,5]表示, (2,3)可用[5,5]表示, (2,3]可用[5,6]表示
3. 计算结果时把倍增的区间缩小回去,可得该区间的范围及其开闭情况
问题:
没有去处理如(4,4)这种不合法区间
代码:
#include <cstdio>
#include <cstring>
#define maxn 131070
struct node
{
int l, r;
int sz;
int xx;
}a[4*maxn];
char ch[20];
int hash[maxn+10];
void Build(int l, int r, int n)
{
a[n].l= l;
a[n].r= r;
a[n].sz= 0;
a[n].xx= 0;
if(l== r)return;
int mid= (a[n].l + a[n].r)/ 2;
Build(l, mid, 2*n);
Build(mid+1, r, 2*n+1);
}
void pushdown(int n)
{
if(a[n].l== a[n].r)
{
a[n].sz= a[n].sz^ a[n].xx;
a[n].xx= 0;
return;
}
if(a[n].sz!=-1)
{
a[2*n].sz= a[2*n+1].sz= a[n].sz;
a[2*n].xx= a[2*n+1].xx= 0;
}
if(a[n].xx)
{
a[2*n].xx^= a[n].xx;
a[2*n+1].xx^= a[n].xx;
a[n].xx= 0;
}
a[n].sz= -1;
}
void update(int l, int r, int n, int num)
{
pushdown(n);
if(a[n].l==l && a[n].r== r)
{
a[n].sz= num;
a[n].xx= 0;
return;
}
int mid= (a[n].l + a[n].r)/ 2;
if(l> mid)
update(l, r, 2*n+1, num);
else if(r<= mid)
update(l, r, 2*n, num);
else
{
update(l, mid, 2*n, num);
update(mid+1, r, 2*n+1, num);
}
}
void XOR(int l, int r, int n, int num)
{
pushdown(n);
if(a[n].l== l && a[n].r== r)
{
a[n].xx^= num;
return;
}
int mid= (a[n].l+ a[n].r)/2;
if(r<= mid)
XOR(l, r, 2*n, num);
else if(l> mid)
XOR(l, r, 2*n+1, num);
else
{
XOR(l, mid, 2*n, num);
XOR(mid+1, r, 2*n+1, num);
}
}
void Query(int n)
{
pushdown(n);
if(a[n].l== a[n].r)
{
hash[a[n].l]= a[n].sz;
return;
}
Query(2*n);
Query(2*n+1);
}
int main()
{
Build(0, maxn, 1);
char cc;
while(scanf("%c",&cc)!=EOF)
{
char f1, f2;
int a, b;
getchar();
scanf("%c%d,%d%c",&f1,&a,&b,&f2);
getchar();
if(f1=='[')
a= 2*a;
else
a= 2*a+ 1;
if(f2== ']')
b= 2*b;
else
b= 2*b- 1;
if(cc== 'U')
{
if(b>= a)
update(a, b, 1, 1);
}
else if(cc== 'I')
{
if(a-1 >=0)
update(0, a-1, 1, 0);
if(b+1<= maxn)
update(b+1, maxn, 1, 0);
}
else if(cc== 'D')
{
if(b>= a)
update(a, b, 1, 0);
}
else if(cc== 'C')
{
if(a-1 >=0)
update(0, a-1, 1, 0);
if(b+1<= maxn)
update(b+1, maxn, 1, 0);
if(b>= a)
XOR(a, b, 1, 1);
}
else if(cc=='S')
{
if(b>= a)
XOR(a, b, 1, 1);
}
}
memset(hash,0, sizeof(hash));
Query(1);
int flag= 0;
int s= -1;
for(int i= 0; i<= maxn+1; i++)
if(hash[i])
{
if(s== -1)
s= i;
}
else if(s!= -1)
{
int t= i-1;
if(flag==0)
{
if(s&1)
printf("(%d,",(s-1)/2);
else
printf("[%d,",s/2);
printf("%d%c",(t+1)/2, t%2? ')' :']');
flag= 1;
}
else
{
printf(" ");
if(s&1)
printf("(%d,",(s-1)/2);
else
printf("[%d,",s/2);
printf("%d%c", (t+1)/2 , t%2? ')' :']' );
}
s= -1;
}
if(!flag)
printf("empty set\n");
else
printf("\n");
return 0;
}