4273. 【NOIP2015模擬10.28B組】聖章-精靈使的魔法語 (File IO): input:elf.in output:elf.out Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits Goto ProblemS ...
4273. 【NOIP2015模擬10.28B組】聖章-精靈使的魔法語
(File IO): input:elf.in output:elf.out
Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
Goto ProblemSet
做法:線段樹,線段樹維護兩個值,一個是當前 區間內有多少個多餘的“(”,另一個值是區間內需要多少個“(”,即有多少個“)” 沒有被匹配,更新一個區間時:(以下右子樹用 right 表示,左子樹用 left 表示): 多餘的“(”=right 多餘的“(”+max(left 多餘的“(”- right 需要的“(” ,0) (取 max 是因為會出現左子樹多餘的“(”還是不夠右子樹用的情況) 需要的“(”=left 需要的“(”+max(right 需要的“(”- left 多餘的“(” ,0) (取 max 是因為會出現右子樹需要的全部的“(” 左子樹都填上了的情況)。
代碼如下:
1 #include <cstring> 2 #include <cstdio> 3 #include <iostream> 4 #include <string> 5 #include <algorithm> 6 #define N 1200007 7 using namespace std; 8 struct tree 9 { 10 int need, more, l, r; 11 }f[N]; 12 int n, m, L, R, x, y; 13 char ch[N / 2]; 14 string c; 15 16 inline int read() 17 { 18 int s = 0; 19 char g = getchar(); 20 while (g < '0' || g > '9') g = getchar(); 21 while (g >= '0' && g <= '9') s = s * 10 + g - '0', g = getchar(); 22 return s; 23 } 24 25 inline string read2() 26 { 27 string gg = ""; 28 char g = getchar(); 29 while (g < 'A' || g > 'z') g = getchar(); 30 while (g >= 'A' && g <= 'z') gg += g, g = getchar(); 31 return gg; 32 } 33 34 inline void put(int x) 35 { 36 if (x < 0) 37 x = ~x + 1, putchar('-'); 38 if (x > 9) 39 put(x / 10);putchar(x % 10 + '0'); 40 } 41 42 inline void build(int p) 43 { 44 if (f[p].l == f[p].r) 45 { 46 if (ch[f[p].l] == '(') f[p].more = 1; 47 else f[p].need = 1; 48 return; 49 } 50 int mid = (f[p].l + f[p].r) / 2; 51 f[p * 2].l = f[p].l; f[p * 2].r = mid; 52 f[p * 2 + 1].l = mid + 1; f[p * 2 + 1].r = f[p].r; 53 build(p * 2); 54 build(p * 2 + 1); 55 f[p].more = f[p * 2 + 1].more + max(f[p * 2].more - f[p * 2 + 1].need, 0); 56 f[p].need = f[p * 2].need + max(f[p * 2 + 1].need - f[p * 2].more, 0); 57 return; 58 } 59 60 inline void change(int p, int t) 61 { 62 if (f[p].l == t && f[p].r == t) 63 { 64 f[p].more = 1 - f[p].more; 65 f[p].need = 1 - f[p].need; 66 return; 67 } 68 if (f[p].l == f[p].r) return; 69 int mid = (f[p].l + f[p].r) / 2; 70 if (t <= mid) change(p * 2, t); 71 else change(p * 2 + 1, t); 72 f[p].more = f[p * 2 + 1].more + max(f[p * 2].more - f[p * 2 + 1].need, 0); 73 f[p].need = f[p * 2].need + max(f[p * 2 + 1].need - f[p * 2].more, 0); 74 return; 75 } 76 77 inline void find(int p, int a, int b) 78 { 79 if (f[p].l == a && f[p].r == b) 80 { 81 L = f[p].need; 82 R = f[p].more; 83 return; 84 } 85 if (f[p].l == f[p].r) return; 86 int mid = (f[p].l + f[p].r) / 2; 87 if (b <= mid) 88 { 89 find(p * 2, a, b); 90 return; 91 } 92 if (a > mid) 93 { 94 find(p * 2 + 1, a, b); 95 return; 96 } 97 find(p * 2, a, mid); 98 int LL = L, RR = R; 99 find(p * 2 + 1, mid + 1, b); 100 int LLL = L, RRR = R; 101 L = LL + max(LLL - RR, 0); 102 R = RRR + max(RR - LLL, 0); 103 return; 104 } 105 106 int main() 107 { 108 // freopen("elf.in", "r", stdin); 109 // freopen("elf.out", "w", stdout); 110 n = read(), m = read(); 111 cin >> ch + 1; 112 f[1].l = 1; f[1].r = n; 113 build(1); 114 while (m--) 115 { 116 c = read2(); 117 if (c == "Query") 118 { 119 L = 0, R = 0; 120 x = read(), y = read(); 121 find(1, x, y); 122 put(L); 123 printf(" "); 124 put(R); 125 printf("\n"); 126 } 127 else 128 { 129 x = read(); 130 change(1, x); 131 } 132 } 133 }