线段树,用 a*2 代表 a 这个点,a*2+1 代表 (a, a+1) 这一段。
五种操作都归结于区间 T 内外的覆盖和取反。具体情况参见一下代码。
#include <iostream>
using namespace std;
#define LEN (65536+1)*2
#define LS (rt*2)
#define RS (rt*2+1)
#define lson rt*2, l, (l+r)/2
#define rson rt*2+1, (l+r)/2+1, r
#define NONE 0
#define COV 1
#define REV 2
struct ST{short f, m;} tt[LEN*4];
int seg[LEN] = {0};
char kh[2][2] = {{'[','('}, {')',']'}};
void DoRev(int rt){
switch (tt[rt].m){
case COV: tt[rt].f = 1-tt[rt].f; break;
case REV: tt[rt].m = 0; break;
case NONE: tt[rt].m = REV; break;
}
}
void pushdown(int rt){
if (tt[rt].m == COV){
tt[LS].f = tt[RS].f = tt[rt].f;
tt[LS].m = tt[RS].m = tt[rt].m;
}
if (tt[rt].m == REV){
DoRev(LS);
DoRev(RS);
}
tt[rt].m = 0;
}
void make_in(char op, int rt){
if (op == 'U') { tt[rt].f=1; tt[rt].m=COV; return; }
if (op == 'D') { tt[rt].f=0; tt[rt].m=COV; return; }
if (op == 'C') { DoRev(rt); return; }
if (op == 'S') { DoRev(rt); return; }
}
void make_out(char op, int rt){
if (op == 'I') { tt[rt].f=0; tt[rt].m=COV; return; }
if (op == 'C') { tt[rt].f=0; tt[rt].m=COV; return; }
}
void pushall(int rt, int l, int r){
if (tt[rt].m == COV || l == r){
for (int i=l; i<=r; i++) seg[i]=tt[rt].f;
return;
}
pushdown(rt);
pushall(lson);
pushall(rson);
}
void update(char op, int b, int e, int rt, int l, int r)
{
if (b > r || e < l) { make_out(op, rt); return; }
if (b <= l && r <= e) { make_in(op, rt); return; }
pushdown(rt);
update(op, b, e, lson);
update(op, b, e, rson);
}
void output(){
int b=0, e, fir = 1;
while (b < LEN){
while (!seg[b]) b++;
if (b > LEN) break;
for (e=b; seg[e+1] && e+1<LEN; e++);
(fir)? fir=0 : printf(" ");
printf("%c%d,%d%c", kh[0][b%2], b/2, (e+1)/2, kh[1][(e+1)%2]);
b=e+1;
}
if (fir) printf("empty set");
printf("\n");
}
int main()
{
memset(tt, 0, sizeof(tt));
tt[1].m = COV;
char op, cl, cr;
int b, e;
while (cin>>op){
scanf(" %c%d,%d%c", &cl, &b, &e, &cr);
b = (cl=='[')? b*2 : b*2+1;
e = (cr==')')? e*2-1 : e*2;
if (b > e){
if (op=='I' || op=='C') { tt[1].f=0; tt[1].m=COV; }
}else
update(op, b, e, 1, 0, LEN);
}
pushall(1, 0, LEN);
output();
return 0;
}