Description
A regular bracket sequence is defined as follows:
Given a bracket sequence S of size N consisting of '(' and ')'. Each time you should simulate one of the following operations:
Input
In the first line there is an integer T (T≤50), indicates the number of test cases. Each case begins with a line containing two integers N (1≤N≤50,000) and M (1≤M≤50,000), the size of the initial brackets sequence and the number of queries. The next line contains N characters consisting of '(' and ')'. Each of the following M lines contains one operation as said above. The index of the bracket sequence is labeled from 1 to N.
Output
For each test case, print a line containing the test case number (beginning with 1) on its own line, then the minimum changes to repair the brackets in [f, r] into a regular brackets sequence for each "Query" operation, one on each line.
Sample Input
Sample Output
Case 1:
1
Case 2:
Case 3:
3
Case 4:
0
此题是继维修数列后的又一道splay维护难题,关键是如何求解最小花费合理括号序列,然后其他的都跟维修数列类似的做法,
然而即便如此,还是调试了半天才搞定,果然还是太弱啊。。。需要注意的是两个延迟标记之间的互相影响。
#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<iostream> #include<algorithm> #include<bitset> #include<functional> using namespace std; typedef unsigned long long ull; typedef long long LL; const int maxn = 1e5 + 10; int T, n, m, l, r, c, root; char s[maxn]; struct Splays { const static int maxn = 1e5 + 10; //节点个数 const static int INF = 0x7FFFFFFF; //int最大值 int ch[maxn][2], F[maxn], sz; //左右儿子,父亲节点和节点总个数 int A[maxn], C[maxn], S[maxn], L[maxn][2], R[maxn][2], Flag[maxn][3]; int Node(int f, int a) { C[sz] = 1; F[sz] = f; S[sz] = A[sz] = a; L[sz][0] = R[sz][0] = min(0, a); L[sz][1] = R[sz][1] = max(0, a); ch[sz][0] = ch[sz][1] = 0; memset(Flag[sz], 0, sizeof(Flag[sz])); return sz++; }//申请一个新节点 void clear(){ sz = 1; ch[0][0] = ch[0][1] = F[0] = 0; L[0][0] = R[0][0] = C[0] = 0; L[0][1] = R[0][1] = S[0] = 0; memset(Flag, 0, sizeof(Flag)); }//清空操作 void swapdown(int x) { Flag[x][1] ^= 1; swap(L[x][0], R[x][0]); swap(L[x][1], R[x][1]); swap(ch[x][0], ch[x][1]); } void invertdown(int x) { if (!Flag[x][0]) Flag[x][2] ^= 1; swap(L[x][0], L[x][1]); swap(R[x][0], R[x][1]); L[x][0] *= -1; L[x][1] *= -1; R[x][0] *= -1; R[x][1] *= -1; A[x] *= -1; S[x] *= -1; } void replacedown(int x, int c) { Flag[x][0] = 1; Flag[x][2] = 0; A[x] = c; S[x] = C[x] * c; L[x][0] = R[x][0] = min(0, S[x]); L[x][1] = R[x][1] = max(0, S[x]); } void pushdown(int x) { if (Flag[x][0]) { if (ch[x][0]) replacedown(ch[x][0], A[x]); if (ch[x][1]) replacedown(ch[x][1], A[x]); } if (Flag[x][1]) { if (ch[x][0]) swapdown(ch[x][0]); if (ch[x][1]) swapdown(ch[x][1]); } if (Flag[x][2]) { if (ch[x][0]) invertdown(ch[x][0]); if (ch[x][1]) invertdown(ch[x][1]); } memset(Flag[x], 0, sizeof(Flag[x])); } void count(int x) { C[x] = C[ch[x][0]] + C[ch[x][1]] + 1; S[x] = S[ch[x][0]] + S[ch[x][1]] + A[x]; L[x][0] = min(L[ch[x][0]][0], S[ch[x][0]] + A[x] + L[ch[x][1]][0]); L[x][1] = max(L[ch[x][0]][1], S[ch[x][0]] + A[x] + L[ch[x][1]][1]); R[x][0] = min(R[ch[x][1]][0], S[ch[x][1]] + A[x] + R[ch[x][0]][0]); R[x][1] = max(R[ch[x][1]][1], S[ch[x][1]] + A[x] + R[ch[x][0]][1]); } void rotate(int x, int k) { int y = F[x]; ch[y][!k] = ch[x][k]; if (ch[x][k]) F[ch[x][k]] = y; if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x; F[x] = F[y]; F[y] = x; ch[x][k] = y; C[x] = C[y]; S[x] = S[y]; L[x][0] = L[y][0]; L[x][1] = L[y][1]; R[x][0] = R[y][0]; R[x][1] = R[y][1]; count(y); } void Splay(int x, int r) { while (F[x] != r) { if (F[F[x]] == r) { rotate(x, x == ch[F[x]][0]); return; } int y = x == ch[F[x]][0], z = F[x] == ch[F[F[x]]][0]; y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y)); } } void build(int fa, int &x, int l, int r) { if (l > r) return; int mid = l + r >> 1; x = Node(fa, s[mid] == '(' ? 1 : -1); build(x, ch[x][0], l, mid - 1); build(x, ch[x][1], mid + 1, r); count(x); } void find(int &x, int k) { for (int i = x; i;) { pushdown(i); if (C[ch[i][0]] > k) { i = ch[i][0]; continue; } if (C[ch[i][0]] == k) { Splay(i, F[x]); x = i; break; } k -= C[ch[i][0]] + 1; i = ch[i][1]; } } int get(int &x, int l, int r) { find(x, l - 1); find(ch[x][1], r - l + 1); return ch[ch[x][1]][0]; } void Swap(int &x, int l, int r) { int g = get(x, l, r); swapdown(g); count(ch[x][1]); count(x); } void Invert(int &x, int l, int r) { int g = get(x, l, r); invertdown(g); count(ch[x][1]); count(x); } void Replace(int &x, int l, int r, int c) { int g = get(x, l, r); replacedown(g, c); count(ch[x][1]); count(x); } void Query(int &x, int l, int r) { int g = get(x, l, r); printf("%d\n", (S[g] - L[g][0] + 1) / 2 + (1 - L[g][0]) / 2); } }solve; int main() { cin >> T; for (int tt = 1; tt <= T; tt++) { solve.clear(); root = 0; scanf("%d%d%s", &n, &m, s + 1); s[0] = s[n + 1] = '('; solve.build(0, root, 0, n + 1); printf("Case %d:\n", tt); while (m--) { scanf("%s%d%d", s, &l, &r); if (s[0] == 'S') solve.Swap(root, l, r); if (s[0] == 'I') solve.Invert(root, l, r); if (s[0] == 'Q') solve.Query(root, l, r); if (s[0] == 'R') scanf("%s", s), solve.Replace(root, l, r, s[0] == '(' ? 1 : -1); } } return 0; }