天天看点

FZU 1978 Repair the brackets

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;
}