题意:
给你几个集合的操作,最后用不想交的集合表示这个集合。
最开始给定的S集合为空。
Command | Semantics |
---|---|
U T | S ← S ∪ T |
I T | S ← S ∩ T |
D T | S ← S − T |
C T | S ← T − S |
S T | S ← S ⊕ T |
思路:
(虽然是在做线段树分类,但是拿到这道题的时候还是一点思路也没有)
首先是怎么来表示这个集合:
由于这个集合有包含端点和不包含端点两种,所以不能简单的用数字带表集合。
需要有数组来表示中间的那一段数字。
我们只需要把每个数字乘2,再对应是否包含端点操作就行了。
进行这样的一个操作后就可以利用线段树进行集合的操作了。
每个操作都可以对应一个操作:
U ::[l, r]置为1
I :(-oo, l) U (r, +oo) 置为0
D:[l, r] 置为0
C:(-oo, l) U (r, +oo)置为0,[l, r] ^ 1
S:[l, r] ^ 1
另外我们注意到如果一个集合都需要修改的化,就不需要进行异或操作了,只需要单纯的修改就可以了。
Code:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<map>
#include<cctype>
#include<vector>
#define TEST
#define LL long long
#define Mt(f, x) memset(f, x, sizeof(f));
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#ifdef TEST
#define See(a) cout << #a << " = " << a << endl;
#define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;
#define debug(a, s, e){ rep(_i, s, e) {cout << a[_i] << ' '; }cout << endl;}
#define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee);}
#else
#define See(a)
#define See2(a, b)
#define debug(a, s, e)
#define debug2(a, s, e, ss, ee)
#endif
const int MAX = 2e9;
const int MIN = -2e9;
const int PI = acos(-1.0);
const double eps = 1e-8;
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int N = 1 << 17;
int f[N << 2], x[N << 2];
bool v[N];
void toXor(int rt)
{
if(f[rt] != -1)<span style="font-family: Arial, Helvetica, sans-serif;">//如果需要改变,就不需要进行异或。</span>
{
f[rt] ^= 1;
}
else
{
x[rt] ^= 1;
}
}
void pushDown(int rt)
{
if(f[rt] != -1) //如果需要改变,就不需要进行异或。
{
f[rt << 1] = f[rt << 1 | 1] = f[rt];
x[rt << 1] = x[rt << 1 | 1] = 0;
f[rt] = -1;
}
if(x[rt])
{
toXor(rt << 1);
toXor(rt << 1 | 1);
x[rt] = 0;
}
}
void update(int L, int R, char op, int l, int r, int rt)
{
if(l >= L && r <= R)
{
if(op == 'U')
{
f[rt] = 1;
x[rt] = 0;
}
else if(op == 'D')
{
f[rt] = 0;
x[rt] = 0;
}
else if(op == 'C' || op == 'S')
{
toXor(rt);
}
return ;
}
pushDown(rt);
int m = (l + r) >> 1;
if(L <= m)
{
update(L, R, op, lson);
}
else if(op == 'I' || op == 'C')//修改[l,r]集合外的断点
{
x[rt << 1] = f[rt << 1] = 0;
}
if(m < R)
{
update(L, R, op, rson);
}
else if(op == 'I' || op == 'C')<span style="font-family: Arial, Helvetica, sans-serif;">//修改[l,r]集合外的断点</span>
{
x[rt << 1 | 1] = f[rt << 1 | 1] = 0;
}
}
void query(int l, int r, int rt)
{
if(f[rt] == 1)
{
for(int i = l; i <= r; ++i)
{
v[i] = true;
}
return ;
}
else if(f[rt] == 0)
{
return ;
}
pushDown(rt);
int m = (l + r) >> 1;
query(lson);
query(rson);
}
int main()
{
char op, l, r;
int a, b;
char ch[100];
f[1] = x[1] = 0;
while(gets(ch))
{
sscanf(ch, "%c %c%d,%d%c", &op, &l, &a, &b, &r);
a = (l == '(' ? a * 2 + 1 : a * 2);
b = (r == ')' ? b * 2 - 1 : b * 2);
if(a > b)
{
if(op == 'I' || op == 'C')
{
f[1] = x[1] = 0;
}
}
else
{
update(a, b, op, 0, N, 1);
}
}
query(0, N, 1);
int st = -1, ed = 0;
bool hasFind = false;
for(int i = 0; i <= N; ++i)
{
if(v[i])
{
if(st == -1)
{
st = i;
}
ed = i;
}
else
{
if(st != -1)
{
if(hasFind)
{
printf(" ");
}
hasFind = true;
printf("%c%d,%d%c", st & 1 ? '(' : '[', st >> 1, (ed + 1) >> 1, ed & 1 ? ')' : ']');
st = -1;
}
}
}
if(!hasFind)
{
printf("empty set\n");
}
return 0;
}