#include <bits/stdc++.h> using namespace std; using ull = unsigned long long; int n, k; vector<bool> word; vector<int> locs; map<tuple<int, int>, ull> gomemo; ull go(int start, int end) { auto it = gomemo.find({start, end}); if (it != gomemo.end()) { return it->second; } // cout << start << " " << end << endl; ull ans = 0; vector<ull> cnt(end - start + 1, 0); int d = 0; for (int i = start; i < end; i++) { if (d < 0) { // cout << "wipe" << " "; for (int j = 1; j < int(cnt.size()) && cnt[j]; j++) cnt[j] = 0; d = 0; } // cout << d << " "; if (word[i]) { d++; } else { if (d) { // cout << "adding" << cnt[d] + 1 << " "; ans += cnt[d] + 1; } for (int j = d + 1; j < int(cnt.size()) && cnt[j]; j++) cnt[j] = 0; cnt[d--]++; } } // cout << "ans: " << ans << endl; return gomemo[{start, end}] = ans; } map<tuple<int, int, int>, ull> memo; ull res(int prev, int next, int rem) { auto it = memo.find({prev, next, rem}); if (it != memo.end()) { return it->second; } ull ans; // cout << prev << " " << next << " " << rem << " = ???" << endl; if (!rem || next >= int(locs.size())) { // ans = (prev >= int(locs.size()) ? 0 : go(locs[prev], n)); ans = go(locs[prev], n); // cout << prev << " " << next << " " << rem << " settle for " << ans << endl; } else { ull ans1 = go(locs[prev], locs[next]) + res(next, next + 1, rem - 1); ull ans2 = res(prev, next + 1, rem); // cout << prev << " " << next << " " << rem << " " << ans1 << " " << ans2 << endl; if (ans1 < ans2) { ans = ans1; // cout << prev << " " << next << " " << rem << " choosing to split" << endl; } else { ans = ans2; // cout << prev << " " << next << " " << rem << " choosing to pass" << endl; } } // cout << prev << " " << next << " " << rem << " = " << ans << endl; // return ans; return memo[{prev, next, rem}] = ans; } void solve() { cin >> n >> k; word = vector<bool>(n); for (int i = 0; i < n; i++) { char c; cin >> c; word[i] = c == '('; } locs.push_back(0); for (int i = 0; i < n - 1; i++) { if (word[i] && !word[i + 1]) locs.push_back(i + 1); } // for (int v : locs) cout << v << " "; // cout << endl; // cout << go(0, n) << endl; cout << res(0, 1, min(k - 1, int(locs.size()))) << endl; // for (int i = 1; i <= n; i++) { // int prev = i - 1; // if (!prev || (word[prev] && !word[i])) { // for (int kk = 0; kk < k; kk++) { // dp2[kk] += dp[prev][kk]; // } // } // if (word[i]) continue; // for (int kk = 1; kk < k; kk++) { // dp[i][kk] += dp2[kk - 1]; // } // } // cout << dp[n][k] << endl; } int main() { ios_base::sync_with_stdio(false); cin.tie(0); // #ifdef LOCAL // int t; cin >> t; while (t--) // #endif solve(); cout.flush(); }
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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | #include <bits/stdc++.h> using namespace std; using ull = unsigned long long; int n, k; vector<bool> word; vector<int> locs; map<tuple<int, int>, ull> gomemo; ull go(int start, int end) { auto it = gomemo.find({start, end}); if (it != gomemo.end()) { return it->second; } // cout << start << " " << end << endl; ull ans = 0; vector<ull> cnt(end - start + 1, 0); int d = 0; for (int i = start; i < end; i++) { if (d < 0) { // cout << "wipe" << " "; for (int j = 1; j < int(cnt.size()) && cnt[j]; j++) cnt[j] = 0; d = 0; } // cout << d << " "; if (word[i]) { d++; } else { if (d) { // cout << "adding" << cnt[d] + 1 << " "; ans += cnt[d] + 1; } for (int j = d + 1; j < int(cnt.size()) && cnt[j]; j++) cnt[j] = 0; cnt[d--]++; } } // cout << "ans: " << ans << endl; return gomemo[{start, end}] = ans; } map<tuple<int, int, int>, ull> memo; ull res(int prev, int next, int rem) { auto it = memo.find({prev, next, rem}); if (it != memo.end()) { return it->second; } ull ans; // cout << prev << " " << next << " " << rem << " = ???" << endl; if (!rem || next >= int(locs.size())) { // ans = (prev >= int(locs.size()) ? 0 : go(locs[prev], n)); ans = go(locs[prev], n); // cout << prev << " " << next << " " << rem << " settle for " << ans << endl; } else { ull ans1 = go(locs[prev], locs[next]) + res(next, next + 1, rem - 1); ull ans2 = res(prev, next + 1, rem); // cout << prev << " " << next << " " << rem << " " << ans1 << " " << ans2 << endl; if (ans1 < ans2) { ans = ans1; // cout << prev << " " << next << " " << rem << " choosing to split" << endl; } else { ans = ans2; // cout << prev << " " << next << " " << rem << " choosing to pass" << endl; } } // cout << prev << " " << next << " " << rem << " = " << ans << endl; // return ans; return memo[{prev, next, rem}] = ans; } void solve() { cin >> n >> k; word = vector<bool>(n); for (int i = 0; i < n; i++) { char c; cin >> c; word[i] = c == '('; } locs.push_back(0); for (int i = 0; i < n - 1; i++) { if (word[i] && !word[i + 1]) locs.push_back(i + 1); } // for (int v : locs) cout << v << " "; // cout << endl; // cout << go(0, n) << endl; cout << res(0, 1, min(k - 1, int(locs.size()))) << endl; // for (int i = 1; i <= n; i++) { // int prev = i - 1; // if (!prev || (word[prev] && !word[i])) { // for (int kk = 0; kk < k; kk++) { // dp2[kk] += dp[prev][kk]; // } // } // if (word[i]) continue; // for (int kk = 1; kk < k; kk++) { // dp[i][kk] += dp2[kk - 1]; // } // } // cout << dp[n][k] << endl; } int main() { ios_base::sync_with_stdio(false); cin.tie(0); // #ifdef LOCAL // int t; cin >> t; while (t--) // #endif solve(); cout.flush(); } |