qoj18246 Deformed Balance

考虑以下两个规则:

\[\begin{align*} e_1&::=\text{LR} \mid e_1e_1\mid \text Le_1\text R \\e_2&::=\text R\mid e_2\text Re_2\mid \text Le_2\text L \end{align*} \]

给定字符串 \(S\),构造 \(T\) 使得:

  • \(S\)\(T\) 的子串。
  • \(T\) 能被 \(e_2\) 生成,\(T\text R\) 能被 \(e_1\) 生成。
  • 最小化 \(|T|\)

\[|S|\le 10^6 \]


规则 \(e_1\) 即为括号序列。

考虑 \(e_2\),我们将其改写为:

\[e_2::=\text R\mid e_2\text Re_2\mid \{e_2\} \]

等价于:

\[e_2::=\text R^{2k+1}\mid\text R^{2k}(\{e_2\}\text R^{2k+1})^k\{e_2\}\text R^{2k} \]

其中 \(k\) 为任意非负整数。

一个重要观察是其中大括号的方向在连续的奇数个 \(\text R\) 后反转。

那么我们尝试判定一个串是否是 Deformed Balance 的,其须在 \(e_1\) 的括号序列和 \(e_2\) 的大括号序列上均合法。为此,我们记录双状态自动机 \((x,y)\) 表示其在 \(e_1\)\(e_2\) 上的前缀和。

若下一个字符是 \(\text L\),转移至 \((x+1,y+(-1)^{x+y})\)

若下一个字符是 \(\text R\),转移至 \((x-1,y)\)

若对于任意时刻均有 \(x,y\ge 0\),且最终状态为 \((1,0)\),其即合法。


然后考虑 \(T=XSY\)

\(XS\) 结束在 \((x',y')\)

\(x'+y'\equiv 1\pmod 2\),只需用 \(y'\)\(\text L\)\(y\)\(0\),然后 \(x'+y'-1\)\(\text R\)\(x\)\(1\)。共需 \(x'+2y'-1\) 次。

否则若 \(x'>0\),只需先一次 \(R\),即可规约至上述情形,次数相同。

否则 \(y\equiv 0\pmod 2\)\(x=0\),需先一次 \(L\) 规约至 \((1,y'+1)\),次数 \(y'+3\)

如此即可 \(\mathcal O(1)\) 计算 \(|Y|_{\min}\)


在前缀 \(X\) 中不会出现 \(\text{RR}\) 子串,否则将其移至 \(Y\) 中,不改变 \(x+y\) 奇偶性,且 \(S\)\(x\) 整体加二,必定不劣。

\(X\) 中出现的 \(\text L\) 连续段不超过 \(2\),因为第 \(3\)\(\text L\) 连续段可以整体前移与第 \(1\)\(\text L\) 连续段拼在一起,因为其奇偶性相同,而移动后 \(y\) 不降,必定不劣。此时其前后的 \(\text R\) 形成 \(\text{RR}\) 子串,与上一个结论矛盾。

由于 \(\text R\) 不能出现在开头,\(X\) 只有以下 \(3\) 种形式:

  • \(\text L^a\)
  • \(\text L^a\text R\text L^b\)
  • \(\text L^a\text R\text L^b\text R\)

由于 \((x,y)\)\(S\) 内的增量只与 \(X\) 末尾时 \(x+y\) 的奇偶性有关,不妨枚举 \(a\)

\(b\) 符合若干线性不等式。解出来后由于有 \(x=0\) 的情况,只有 \(b_{\min}\) 附近的 \(\mathcal O(1)\) 个值需要枚举。

总时间复杂度 \(\mathcal O(n)\)


#include <iostream>
#include <algorithm>

const int N = 1e6 + 7;

int n, v[N];

inline void step(int& x, int& y, int w) {
  if(w) y += (x + y) & 1 ? -1 : 1, ++x;
  else --x;
}

int ans = 1e9;

inline int calc(int x, int y) {
  return 2 * y + (x == 0 && y % 2 == 0 ? 3 : x - 1);
}

inline void even() {
  int x = 0, y = 0, mx = 0, my = 0;
  for(int i = 1; i <= n; ++i) {
    step(x, y, v[i]);
    mx = std::min(mx, x), my = std::min(my, y);
  }
  // LaRLbR => (a+b-2, a-b)
  // a+b-2 >= -mx, a-b >= -my
  // ends in (a+b-2+x, a-b+y)
  for(int a = 1; a <= n; ++a) {
    int bD = 1, bU = a;
    bD = std::max(bD, 2-a-mx);
    bU = std::min(bU, a + my);
    if(bD <= bU) {
      int b = bD;
      int fx = a + b - 2 + x, fy = a - b + y;
      ans = std::min(ans, calc(fx, fy) + a + b + 2);
      if(fx == 0 && fy % 2 == 0 && ++b <= bU) {
        ++fx, --fy;
        ans = std::min(ans, calc(fx, fy) + a + b + 2);
      }
    }
  }
  // La => (a,a)
  // a >= -mx, a >= -my
  for(int a = 0; a <= n; ++a) {
    if(a + mx >= 0 && a + my >= 0) {
      int fx = a + x, fy = a + y;
      ans = std::min(ans, calc(fx, fy) + a);
    }
  }
}

inline void odd() {
  int x = 1, y = 0, mx = 1, my = 0;
  for(int i = 1; i <= n; ++i) {
    step(x, y, v[i]);
    mx = std::min(mx, x), my = std::min(my, y);
  }
  // LaRLb => (a+b-1, a-b)
  // a+b-2 >= -mx, a-b >= -my
  // ends in (a+b-2+x, a-b+y)
  for(int a = 1; a <= n; ++a) {
    int bD = 0, bU = a;
    bD = std::max(bD, 2-a-mx);
    bU = std::min(bU, a + my);
    if(bD <= bU) {
      int b = bD;
      int fx = a + b - 2 + x, fy = a - b + y;
      ans = std::min(ans, calc(fx, fy) + a + b + 1);
      if(fx == 0 && fy % 2 == 0 && ++b <= bU) {
        ++fx, --fy;
        ans = std::min(ans, calc(fx, fy) + a + b + 1);
      }
    }
  }
}

inline void solve() {
  std::cin >> n;
  for(int i = 1; i <= n; ++i) {
    char c; std::cin >> c;
    v[i] = c == '(';
  }
  ans = 1e9;
  even(), odd();
  std::cout << ans << "\n";
}

int main() {
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int t; std::cin >> t; while(t--) solve();
}
posted @ 2026-08-21 01:40  CuteNess  阅读(10)  评论(0)    收藏  举报