SDOI 2008 校门外的区间

Posted milky-w

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SDOI 2008 校门外的区间相关的知识,希望对你有一定的参考价值。

题目:BZOJ 3226

注意这个题目中的区间表示一个个线段,而不是点集。比如 (2,3) 表示的是 2 与 3 中间的部分,而不是空集。

可以说这是一道线段树的入门题,很容易想到用 0 和 1 表示这个点在不在集合 S 中,并新增加一倍的节点用来表示点与点之间的部分。

通过画 Venn 图来演示,可以得出以下几种处理方法:

U -> S |= T

I -> 置零 [ S ∩ (Cu T) ]

D -> 置零 [ S ∩ T ]

C -> 取反 [ S ] -> 操作 I

S -> S ^= T

对线段树的每个节点打个标记,取反记为 1,置 0 记为 2,置 1 记为 3,可以得出:

father —> son

取反 —> 置 0 = 置 1

取反 —> 置 1 = 置 0

取反 —> 取反 = 无 

置 0 —> 置 1 = 置 0

置 0 —> 取反 = 置 0

置 1 —> 置 0 = 置 1

置 1 —> 取反 = 置 1

这是我的代码,虽然过了但是 BZOJ 倒数。

 

  1 /**************************************************************
  2     Problem: 3226
  3     User: MilkyWay
  4     Language: C++
  5     Result: Accepted
  6     Time:1800 ms
  7     Memory:99636 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <string>
 12  
 13 const int N = 131072;
 14  
 15 struct Node {
 16     Node *ls, *rs;
 17     int tag;
 18     Node() : tag(0) {}
 19 } Pool[N << 1 + 5], *root;
 20  
 21 Node *newNode() {
 22     static int cnt = 0;
 23     return &Pool[++cnt];
 24 }
 25  
 26 void build(Node *&cur, int l, int r) {
 27     if (!cur) cur = newNode();
 28     if (l == r) cur->tag = 2;
 29     else {
 30         int mid = l + ((r - l) >> 1);
 31         build(cur->ls, l, mid);
 32         build(cur->rs, mid + 1, r);
 33     }
 34 }
 35  
 36 void pushdown(Node *&cur, int l, int r) {
 37     if (cur->ls) {
 38         if (cur->ls->tag == 0) cur->ls->tag = cur->tag;
 39         else if (cur->tag == 1) cur->ls->tag ^= 1;
 40         else if (cur->tag == 2) cur->ls->tag = 2;
 41         else cur->ls->tag = 3;
 42     }
 43     if (cur->rs) {
 44         if (cur->rs->tag == 0) cur->rs->tag = cur->tag;
 45         else if (cur->tag == 1) cur->rs->tag ^= 1;
 46         else if (cur->tag == 2) cur->rs->tag = 2;
 47         else cur->rs->tag = 3;
 48     }
 49     cur->tag = 0;
 50 }
 51  
 52 void update(Node *&cur, int l, int r, int L, int R, int key) {
 53     if (!cur) return;
 54     if (L <= l && r <= R) {
 55         if (key == 1) cur->tag ^= 1;
 56         else if (key == 2) cur->tag = 2;
 57         else cur->tag = 3;
 58     } else {
 59         if (cur->tag) pushdown(cur, l, r);
 60         int mid = l + ((r - l) >> 1);
 61         if (L <= mid) update(cur->ls, l, mid, L, R, key);
 62         if (mid < R) update(cur->rs, mid + 1, r, L, R, key);
 63     }
 64 } 
 65  
 66 int Q[N + 5], cnt;
 67  
 68 void query(Node *&cur, int l, int r) {
 69     if (!cur) return;
 70     if (l == r) {
 71         if (cur->tag == 3) Q[++cnt] = l;
 72     } else {
 73         if (cur->tag) pushdown(cur, l, r);
 74         int mid = l + ((r - l) >> 1);
 75         query(cur->ls, l, mid);
 76         query(cur->rs, mid + 1, r);
 77     }
 78 }
 79  
 80 int main() { // 1 -> 取反; 2 -> 置 0; 3 -> 置 1
 81     build(root, 1, N);
 82     char opt;
 83     while (~scanf("%c ", &opt)) {
 84         int l, r; char c, d;
 85         scanf("%c%d,%d%c\n", &c, &l, &r, &d);
 86         ++ l, ++ r;
 87         l = (l << 1) - 1, r = (r << 1) - 1;
 88         if (c == () ++ l;
 89         if (d == )) -- r;
 90         if (opt == U) {
 91             update(root, 1, N, l, r, 3);
 92         } else if (opt == I) {
 93             update(root, 1, N, 1, l - 1, 2);
 94             update(root, 1, N, r + 1, N, 2);
 95         } else if (opt == D) {
 96             update(root, 1, N, l, r, 2);
 97         } else if (opt == C) {
 98             update(root, 1, N, 1, N, 1);
 99             update(root, 1, N, 1, l - 1, 2);
100             update(root, 1, N, r + 1, N, 2);
101         } else if (opt == S) {
102             update(root, 1, N, l, r, 1);
103         }
104     }
105     query(root, 1, N);
106     if (cnt == 0) puts("empty set");
107     else {
108         Q[0] = Q[cnt + 1] = -100;
109         for (int i = 1; i <= cnt; ++ i) {
110             if (Q[i - 1] + 1 != Q[i]) {
111                 if (Q[i] & 1) printf("[%d,", Q[i] - 1 >> 1);
112                 else printf("(%d,", Q[i] - 2 >> 1);
113             }
114             if (Q[i] + 1 != Q[i + 1]) {
115                 if (Q[i] & 1) printf("%d] ", Q[i] - 1 >> 1);
116                 else printf("%d) ", Q[i] >> 1);
117             }
118         }
119     }
120     return 0;
121 }

以上是关于SDOI 2008 校门外的区间的主要内容,如果未能解决你的问题,请参考以下文章

SDOI 2008 校门外的区间

[bzoj 3226]校门外的区间

校门外的树

P1047 校门外的树

[TYVJ1473]校门外的树3

校门外的树