CF1976D

下面给出一个线性做法,( 当成 \(1\)) 当成 \(-1\)\(s_i\) 为前缀和数组。
那么翻转 \([l, r]\)\(s_n\) 会减少 \(2(s_r - s_{l - 1})\),由于 \(s_n\) 一直是 \(0\),所以要求 \(s_r = s_{l - 1}\)
但是同时还要求翻转后 \(\forall k \in [l, r], s_k \ge 0\),相当于 \(s_{l - 1} + s_r - s_k = 2s_r - s_k \ge 0\),所以当某一个 \(s_k\) 达到了 \(2x + 1\),那么前面所有 \(s_{l - 1} = x\)\(l\) 就不能作为左端点了。
注意非空合法串的反串一定不合法,所以要去掉 \(s_r = 0\) 的情况。
时间复杂度 \(\mathcal{O}(n)\)

namespace Loop1st {
int n, mp[N];
char str[N];
ll ans;
void Main(int tc) {
    ans = 0;
    cin >> (str + 1);
    n = strlen(str + 1);
    memset(mp, 0, n << 2);
    for (int i = 1, s = 0; i <= n; i++) {
        s += (str[i] == '(') ? 1 : -1;
        if (s & 1) mp[s >> 1] = 0;
        if (s) ans += mp[s]++;
    } 
    cout << ans << '\n';
}

}
posted @ 2026-04-08 18:25  循环一号  阅读(5)  评论(0)    收藏  举报