Description
A regular bracket sequence is defined as follows:
1. Empty sequence is a regular bracket sequence.2. If S is a regular bracket sequence, then (S) is also a regular bracket sequence.3. If a and b are regular bracket sequences, then ab is a regular bracket sequence.4. Any other sequences are not regular bracket sequences.
Given a bracket sequence S of size N consisting of '(' and ')'. Each time you should simulate one of the following operations:
1. Replace f r c: Replace all brackets by c in [f, r].2. Swap f r: Reverse all brackets in [f, r].3. Invert f r: Invert all brackets in [f, r] from '(' to ')' and vice versa.4. Query f r: Output the minimum changes to repair the brackets in [f, r] intoa regular bracket sequence. To repair the brackets each time you can invert abracket from '(' to ')' or vice versa. For example, you need 2 changes to repair "((((" to "(())" by inverting the last two '(' to ')'. The length of the query sequence, that is r-f+1, will always be even.
You should note that f and r will fit 1≤f≤r≤N, c is either '(' or ')'.
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
4
2 2
((
Invert 1 2
Query 1 2
3 1
(()
Invert 1 3
8 4
)))()()(
Invert 6 7
Swap 3 6
Replace 5 7 (
Query 4 7
9 3
(())()(()
Swap 1 7
Replace 8 9 (
Query 1 4
Sample Output
Case 1:
1
Case 2:
Case 3:
3
Case 4:
此题是继维修数列后的又一道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;
}