POJ 3225 区间(带标记的线段树区间操作)
思路:
1. 因为要对一个区间进行多种操作,特别是相补差和对称差的情况下,要对一个区间操作怎么办?
2. 区间的seg[] = 0, 1, -1,分别表示区间为空,有数据,两者兼有。lab[] = 0, 1 表示区间是否被标记,当seg[] = -1时才会有效(即不确定时)
3. 对区间的5中操作,其实标记主要是为了应对于取反的操作。也算是延迟的一种方式吧,大区间取反,虽然其中可能有0,1,-1,但是最终只是针对0,1取反的。
U:把区间[l,r]覆盖成1
I:把[-∞,l)(r,∞]覆盖成0
D:把区间[l,r]覆盖成0
C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换
S:[l,r]区间0/1互换
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define lhs l, m, rt << 1
#define rhs m + 1, r, rt << 1 | 1
const int maxn = 131100;
bool hash[maxn];
int seg[maxn << 2];
int lab[maxn << 2];
void DoXor(int rt)
{
if (seg[rt] != -1)
seg[rt] = seg[rt] ^ 1;
else
lab[rt] = lab[rt] ^ 1;
}
void PushDown(int rt)
{
if (seg[rt] != -1)
{
seg[rt << 1] = seg[rt << 1 | 1] = seg[rt];
lab[rt << 1] = lab[rt << 1 | 1] = 0;
seg[rt] = -1;
}
if (lab[rt])
{
DoXor(rt << 1);
DoXor(rt << 1 | 1);
lab[rt] = 0;
}
}
void Update(char op, int beg, int end, int l, int r, int rt)
{
if (beg <= l && r <= end)
{
if (op == 'U')
seg[rt] = 1, lab[rt] = 0;
else if (op == 'D')
seg[rt] = 0, lab[rt] = 0;
else if (op == 'C' || op == 'S')
DoXor(rt);
}
else
{
PushDown(rt);
int m = (l + r) >> 1;
if (beg <= m)
Update(op, beg, end, lhs);
else if (op == 'I' || op == 'C')
seg[rt << 1] = lab[rt << 1] = 0;
if (end > m)
Update(op, beg, end, rhs);
else if (op == 'I' || op == 'C')
seg[rt << 1 | 1] = lab[rt << 1 | 1] = 0;
}
}
void Query(int l, int r, int rt)
{
if (seg[rt] == 1)
{
for (int i = l; i <= r; ++i)
hash[i] = true;
return ;
}
else if (seg[rt] == 0 || l == r)
return ;
PushDown(rt);
int m = (l + r) >> 1;
Query(lhs); Query(rhs);
}
int main()
{
seg[1] = lab[1] = 0;
char op, l, r;
int a, b;
while (scanf("%c %c%d,%d%c\n", &op, &l, &a, &b, &r) != EOF)
{
a <<= 1, b <<= 1;
if (l == '(')
++a;
if (r == ')')
--b;
if (a > b)
{
if (op == 'C' || op == 'I')
seg[1] = lab[1] = 0;
}
else
Update(op, a, b, 0, maxn, 1);
}
Query(0, maxn, 1);
bool flag = false;
int 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 (flag) printf(" ");
flag = true;
printf("%c%d,%d%c",s&1?'(':'[' , s>>1 , (e+1)>>1 , e&1?')':']');
s = -1;
}
}
}
if (!flag) printf("empty set");
printf("\n");
return 0;
}
-------------------------------------------------------
kedebug
Department of Computer Science and Engineering,
Shanghai Jiao Tong University
E-mail: kedebug0@gmail.com
GitHub: http://github.com/kedebug
-------------------------------------------------------