写个总结吧, 因为挺多细节的
然后, 问题就解决了.
#include <cstdio> using namespace std; char str[30000 + 10]; int N; int src[30000 + 10]; struct _Node { _Node * left, * right; int min; int add; }; typedef _Node * NodePtr; template<class T> inline T getMin(T & a, T & b) { return a < b ? a : b; } _Node __nodelist[(30000 + 10) * 4]; int __top = 0; NodePtr newNode() { return &(__nodelist[__top ++]); } NodePtr makeTree(int a, int z) { if (a == z) { NodePtr cur = newNode(); cur->left = cur->right = NULL; cur->min = src[a]; cur->add = 0; return cur; } int mid = a + (z -a ) / 2; NodePtr cur = newNode(); cur->left = makeTree(a, mid); cur->right = makeTree(mid + 1, z); cur->min = getMin(cur->left->min, cur->right->min); cur->add = 0; return cur; } void pushDown(NodePtr cur) { if (cur == NULL) return; if (cur->add == 0) return; cur->min = cur->min + cur->add; if (cur->left) cur->left->add += cur->add; if (cur->right) cur->right->add += cur->add; cur->add = 0; return; } inline bool common(int a, int b, int c, int d) { return !(b < c || d < a); } void change(NodePtr cur, int a, int z, int start, int end, int val) { //只要进入一个节点就要pushDown一次 pushDown(cur); if (start <= a && z <= end) { cur->add = val; pushDown(cur); return; } int mid = a + (z -a ) / 2; if (common(a, mid, start, end)) change(cur->left, a, mid, start, end, val); if (common(mid + 1, z, start, end)) change(cur->right, mid + 1, z, start, end, val); //注意下面的两个pushDown, 是非常容易遗漏的, 如果不写, 想想会有什么问题, 呵呵 pushDown(cur->left); pushDown(cur->right); cur->min = getMin(cur->left->min, cur->right->min); return; } NodePtr getNode(NodePtr cur, int a, int z, int pos) { //只要进入一个节点就要pushDown一次 pushDown(cur); if (a == z && a == pos) return cur; int mid = a + (z -a ) / 2; if (pos <= mid) return getNode(cur->left, a, mid, pos); else return getNode(cur->right, mid + 1, z, pos); } NodePtr root; void run() { scanf("%d", &N); scanf("%s", str + 1); int i; src[0] = 0; for (i = 1; str[i]; ++i) { if (str[i] == '(') { src[i] = src[i - 1] + 1; } else { src[i] = src[i - 1] - 1; } } __top = 0; root = makeTree(1, N); int M; scanf("%d", &M); for (i = 1; i <= M; ++i) { int x; scanf("%d", &x); if (x == 0) { pushDown(root); //printf("root->min %d\n", root->min); if ( root->min >= 0 && (getNode(root, 1, N, N)->min == 0)) printf("YES\n"); else printf("NO\n"); } else { if (str[x] == '(') { str[x] = ')'; change(root, 1, N, x, N, -2); } else { str[x] = '('; change(root, 1, N, x, N, 2); } } } } int curCase; int main() { for (curCase = 1; curCase <= 10; ++curCase) { printf("Test %d:\n", curCase); run(); } return 0; }