题解 P5568 【[SDOI2008]校门外的区间】

ModestCoder_

2019-10-13 16:13:52

Solution

转化成线段树的区间覆盖+翻转问题 用线段树维护当前区间 并且维护两个标记$cov,tag$,分别代表覆盖和翻转的标记 - $U:B$区间覆盖1 - $I:B$区间的补集覆盖0 - $D:B$区间覆盖0 - $C:$全集范围内01翻转,转到$I$操作 - $S:B$区间范围内01翻转 细节处理 - 输入输出细节 - 开闭用*2方法处理 - 覆盖和翻转的优先级 Code: ```cpp #include <bits/stdc++.h> #define maxn 132010 #define ls rt << 1 #define rs rt << 1 | 1 using namespace std; struct Seg{ int l, r, cov, tag; }seg[maxn << 2]; int ans[maxn], n = maxn; char s[20]; void get(int &l, int &r){ char c = getchar(); for (; c != '(' && c != '['; c = getchar()); int w = c == '('; l = 0; for (; !isdigit(c); c = getchar()); for (; isdigit(c); c = getchar()) l = (l << 1) + (l << 3) + (c ^ 48); l <<= 1; l += w, r = 0; for (; !isdigit(c); c = getchar()); for (; isdigit(c); c = getchar()) r = (r << 1) + (r << 3) + (c ^ 48); r <<= 1; for (; c != ')' && c != ']'; c = getchar()); r -= c == ')'; } void pushdown(int rt){ if (seg[rt].cov != -1){ seg[ls].cov = seg[rs].cov = seg[rt].cov; seg[ls].tag = seg[rs].tag = 0; seg[rt].cov = -1; } if (seg[rt].tag){ seg[ls].tag ^= 1, seg[rs].tag ^= 1; seg[rt].tag = 0; } } void build(int rt, int l, int r){ seg[rt].l = l, seg[rt]. r = r, seg[rt].cov = -1; if (l == r) return; int mid = (l + r) >> 1; build(ls, l, mid), build(rs, mid + 1, r); } void update(int rt, int l, int r, int k){ if (seg[rt].l > r || seg[rt].r < l || l > r) return; if (seg[rt].l >= l && seg[rt].r <= r){ if (k != 2) seg[rt].cov = k, seg[rt].tag = 0; else seg[rt].tag ^= 1; return; } pushdown(rt); update(ls, l, r, k), update(rs, l, r, k); } void query(int rt){ if (seg[rt].l == seg[rt].r){ ans[seg[rt].l] = seg[rt].cov == -1 ? 0 : seg[rt].cov ^ seg[rt].tag; return; } pushdown(rt); query(ls), query(rs); } void print(){ query(1); int flag = 0, Empty = 0; for (int i = 0; i <= n; ++i){ if (ans[i] && !flag){ flag = Empty = 1; if (i & 1) printf("(%d,", (i - 1) >> 1); else printf("[%d,", i >> 1); } if (!ans[i] && flag){ flag = 0; if (i & 1) printf("%d] ", (i - 1) >> 1); else printf("%d) ", i >> 1); } } if (!Empty) puts("empty set"); } int main(){ build(1, 0, n); while (scanf("%s", s) != EOF){ int l, r; get(l, r); if (s[0] == 'U') update(1, l, r, 1); else if (s[0] == 'I') update(1, 0, l - 1, 0), update(1, r + 1, n, 0); else if (s[0] == 'D') update(1, l, r, 0); else if (s[0] == 'C') update(1, 0, n, 2), update(1, 0, l - 1, 0), update(1, r + 1, n, 0); else update(1, l, r, 2); } print(); return 0; } ```