#include <bits/stdc++.h> using namespace std; const int MAXN = 100'007; char s[MAXN]; int sum[MAXN]; vector<int> where[MAXN * 2]; pair<int, int> prev_sums[MAXN]; int prev_sums_last; tuple<long long, int, int> dp[MAXN]; int dp_last; void calc_dp(int n, long long penalty) { prev_sums[0] = make_pair(sum[0], 0); prev_sums_last = 0; dp[0] = make_tuple(0ll, 0, 0); dp_last = 0; for (int i = 1; i <= n; i++) { while (prev_sums_last >= 0 && sum[i] <= prev_sums[prev_sums_last].first) { prev_sums_last--; } int bound = 0; if (prev_sums_last >= 0) { bound = prev_sums[prev_sums_last].second + 1; } prev_sums[++prev_sums_last] = make_pair(sum[i], i); if (s[i - 1] == ')') { int my_pos = lower_bound(where[sum[i]].begin(), where[sum[i]].end(), i) - where[sum[i]].begin(); for (int j = 0; j <= dp_last; j++) { get<0>(dp[j]) += my_pos - (lower_bound(where[sum[i]].begin(), where[sum[i]].end(), max(bound, get<2>(dp[j]))) - where[sum[i]].begin()); } int tmp = dp_last; dp_last = -1; for (int j = 0; j <= tmp; j++) { while (dp_last >= 0 && get<0>(dp[dp_last]) >= get<0>(dp[j])) { dp_last--; } assert(++dp_last <= j); if (dp_last != j) { dp[dp_last] = dp[j]; } } } tuple<long long, int, int> me = make_tuple(get<0>(dp[0]) + penalty, get<1>(dp[0]) + 1, i); while (dp_last >= 0 && get<0>(dp[dp_last]) >= get<0>(me)) { dp_last--; } dp[++dp_last] = me; } } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, k; cin >> n >> k >> s; sum[0] = n; where[n].emplace_back(0); for (int i = 1; i <= n; i++) { if (s[i - 1] == '(') { sum[i] = sum[i - 1] + 1; } else { sum[i] = sum[i - 1] - 1; } where[sum[i]].emplace_back(i); } long long low = 0, high = 1e12 + 7; while (low < high) { long long mid = (low + high + 1) >> 1; calc_dp(n, mid); if (get<1>(dp[dp_last]) >= k) { low = mid; } else { high = mid - 1; } } calc_dp(n, high); long long result = get<0>(dp[dp_last]) - high * k; cout << result << '\n'; return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | #include <bits/stdc++.h> using namespace std; const int MAXN = 100'007; char s[MAXN]; int sum[MAXN]; vector<int> where[MAXN * 2]; pair<int, int> prev_sums[MAXN]; int prev_sums_last; tuple<long long, int, int> dp[MAXN]; int dp_last; void calc_dp(int n, long long penalty) { prev_sums[0] = make_pair(sum[0], 0); prev_sums_last = 0; dp[0] = make_tuple(0ll, 0, 0); dp_last = 0; for (int i = 1; i <= n; i++) { while (prev_sums_last >= 0 && sum[i] <= prev_sums[prev_sums_last].first) { prev_sums_last--; } int bound = 0; if (prev_sums_last >= 0) { bound = prev_sums[prev_sums_last].second + 1; } prev_sums[++prev_sums_last] = make_pair(sum[i], i); if (s[i - 1] == ')') { int my_pos = lower_bound(where[sum[i]].begin(), where[sum[i]].end(), i) - where[sum[i]].begin(); for (int j = 0; j <= dp_last; j++) { get<0>(dp[j]) += my_pos - (lower_bound(where[sum[i]].begin(), where[sum[i]].end(), max(bound, get<2>(dp[j]))) - where[sum[i]].begin()); } int tmp = dp_last; dp_last = -1; for (int j = 0; j <= tmp; j++) { while (dp_last >= 0 && get<0>(dp[dp_last]) >= get<0>(dp[j])) { dp_last--; } assert(++dp_last <= j); if (dp_last != j) { dp[dp_last] = dp[j]; } } } tuple<long long, int, int> me = make_tuple(get<0>(dp[0]) + penalty, get<1>(dp[0]) + 1, i); while (dp_last >= 0 && get<0>(dp[dp_last]) >= get<0>(me)) { dp_last--; } dp[++dp_last] = me; } } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, k; cin >> n >> k >> s; sum[0] = n; where[n].emplace_back(0); for (int i = 1; i <= n; i++) { if (s[i - 1] == '(') { sum[i] = sum[i - 1] + 1; } else { sum[i] = sum[i - 1] - 1; } where[sum[i]].emplace_back(i); } long long low = 0, high = 1e12 + 7; while (low < high) { long long mid = (low + high + 1) >> 1; calc_dp(n, mid); if (get<1>(dp[dp_last]) >= k) { low = mid; } else { high = mid - 1; } } calc_dp(n, high); long long result = get<0>(dp[dp_last]) - high * k; cout << result << '\n'; return 0; } |