spoj61.Brackets(线段树)

来源:互联网 发布:卡祖笛 知乎 编辑:程序博客网 时间:2024/04/27 15:48

维护一个长度为 N 的小括号序列,实现两个操作:①将第i 个位置的括号取反;②测试当前序列是否合法。

线段树维护两个变量:①区间内没有匹配的左括号数;②区间内没有匹配的右括号数。当这个区间的这两个变量都为0 时序列合法。

/*Author: JDDPROG: spoj61.BracketsDATE: 2015.12.07*/#include <cstdio>#include <algorithm>using namespace std;const int MAX_N = 30005;struct node{int l, r, lx, rx;}a[MAX_N << 2];int n, m;char s[MAX_N];void update(int i){int t1 = i << 1, t2 = t1 | 1;a[i].lx = a[t1].lx + a[t2].lx - min(a[t1].lx, a[t2].rx);a[i].rx = a[t1].rx + a[t2].rx - min(a[t1].lx, a[t2].rx);}void make_tree(int i, int l, int r){a[i].l = l; a[i].r = r; a[i].lx = a[i].rx = 0;if (l == r){if (s[l] == '(') a[i].lx = 1;else a[i].rx = 1;return;}int mid = (a[i].l + a[i].r) >> 1, t1 = i << 1, t2 = t1 | 1;make_tree(t1, l, mid); make_tree(t2, mid + 1, r);update(i);}void tree_change(int i, int x){if (a[i].l == a[i].r){a[i].lx ^= 1; a[i].rx ^= 1; return;}int mid = (a[i].l + a[i].r) >> 1, t1 = i << 1, t2 = t1 | 1;if (x <= mid) tree_change(t1, x);else tree_change(t2, x);update(i); }void init(){scanf("%s", s + 1);make_tree(1, 1, n);}void doit(){scanf("%d", &m);for (int i = 1; i <= m; i ++){int x; scanf("%d", &x);if (!x){if (a[1].lx || a[1].rx) printf("NO\n");else printf("YES\n");} else tree_change(1, x);}}int main(){int tot = 0;while (scanf("%d", &n) != EOF){printf("Test %d:\n", ++ tot);init();doit();}return 0;}


0 0