qoj18246 Deformed Balance
考虑以下两个规则:
给定字符串 \(S\),构造 \(T\) 使得:
- \(S\) 是 \(T\) 的子串。
- \(T\) 能被 \(e_2\) 生成,\(T\text R\) 能被 \(e_1\) 生成。
- 最小化 \(|T|\)。
规则 \(e_1\) 即为括号序列。
考虑 \(e_2\),我们将其改写为:
等价于:
其中 \(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();
}
本文来自博客园,作者:CuteNess,转载请注明原文链接:https://www.cnblogs.com/CuteNess/p/22591872

浙公网安备 33010602011771号