题解:P9805 [POI2022~2023R1] ply
Albatross_LC · · 题解
模拟赛里出了,见有原题,便来水一发题解。
思路:
我们可以把原字符串中的 ( 记为 ) 记为
给定一个长度为
n 序列a ,每次选择一个数i(1\le i\le n) ,将a_i 到a_n 都加或减1 ,使得序列a 中的数最大值不超过L ,最小值不小于0 ,求最小操作次数
注:此处 ),每次匹配的 ( 总在 ) 的左边,所以遍历到
此时问题就很简单了,我么只需要对前缀和数组
Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int read() {
int res = 0, c = getchar(), s = 0;
while (!isdigit(c)) s |= c == '-',c = getchar();
while (isdigit(c)) res = (res << 1) + (res << 3) + c - '0', c = getchar();
return s ? -res : res;
}
int n, l, a[N], mx, ans;
char s[N];
int main() {
n = read(), l = read();
scanf("%s", s + 1);
for (int i = 1; i <= n; i ++ )
a[i] = a[i - 1] + (s[i] == '(' ? 1 : -1), mx = max(mx, a[i]);
if (mx <= l) cout << 0, exit(0);
int tot = 0;
for (int i = 1; i <= n; i ++ )
if (a[i] - tot > l) {
ans ++ ;
tot += 2;
} else if (a[i] - tot < 0) {
ans ++ ;
tot -= 2;
}
cout << ans;
}