1. 程式人生 > >SDOI 2008 校門外的區間

SDOI 2008 校門外的區間

clu root ont ron spa build cap 得出 char

題目: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 校門外的區間