#include <cstdio> #include <algorithm> #define scanf(...) scanf(__VA_ARGS__)?:0 typedef long long ll; using namespace std; #define INF 1e18 int n, k, w[100005], _ost[200005], _pre[200005], *ost = _ost + 100000, *pre = _pre+100000; int ilel[100005], ostl[100005], ilep[100005], ostp[100005]; char s[100005]; int _ile[200005], *ile = _ile + 100000; ll wynik[2][100005]; struct Iv { int a=0, b=0; ll podslowa = 0; void exr() { b++; if (ostl[b] < a) podslowa += ile[w[b]]; else podslowa += ilel[b]; ile[w[b]]++; } void exl() { a--; if (ostp[a+1]-1 > b) podslowa += ile[w[a]]; else podslowa += ilep[a+1]; ile[w[a]]++; } void shr() { ile[w[b]]--; if (ostl[b] < a) podslowa -= ile[w[b]]; else podslowa -= ilel[b]; b--; } void shl() { ile[w[a]]--; if (ostp[a+1]-1 > b) podslowa -= ile[w[a]]; else podslowa -= ilep[a+1]; a++; } void przejdz(int c, int d) { while (b < d) exr(); while (a > c) exl(); while (b > d) shr(); while (a < c) shl(); } } przedzial; void obsluz(int a, int b, int u, int v) { int s = (a + b) / 2; int w = min(v, s); ll optw = INF; int najl = 0; for (int i = w; i >= u; i--) { przedzial.przejdz(i-1,s); if (wynik[0][i-1] + przedzial.podslowa < optw) { optw = wynik[0][i-1] + przedzial.podslowa; najl = i; } } wynik[1][s] = optw; if (s > a) obsluz(a, s-1, u, najl); if (s < b) obsluz(s+1, b, najl, v); } int main() { scanf("%d%d %s", &n, &k, s+1); ile[0] = 1; for (int i = 1; i <= n; i++) { w[i] = w[i-1] + (s[i] == '(' ? 1 : -1); if ((ost[w[i]] == 0 && w[i] != 0) || ost[w[i]-1] > ost[w[i]]) { ostl[i] = pre[w[i]] = i; ilel[i] = 0; } else { ostl[i] = pre[w[i]]; ilel[i] = ilel[ost[w[i]]] + 1; } ost[w[i]] = i; } for (int i = -n; i <= n; i++) ost[i] = n+1, pre[i] = n+1; int ww = 0; for (int i = n; i > 0; i--) { ww += (s[i] == ')' ? 1 : -1); if ((ost[ww] == n+1 && ww != 0) || ost[ww-1] < ost[ww]) { ostp[i] = pre[ww] = i; ilep[i] = 0; } else { ostp[i] = pre[ww]; ilep[i] = ilep[ost[ww]] + 1; } ost[ww] = i; } for (int i = 1; i <= n; i++) { przedzial.przejdz(0,i); wynik[0][i] = przedzial.podslowa; } for (int i = 1; i < k; i++) { obsluz(1, n, 1, n); for (int i = 1; i <= n; i++) { wynik[0][i] = wynik[1][i]; wynik[1][i] = 0; } } printf("%lld\n", wynik[0][n]); }
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 | #include <cstdio> #include <algorithm> #define scanf(...) scanf(__VA_ARGS__)?:0 typedef long long ll; using namespace std; #define INF 1e18 int n, k, w[100005], _ost[200005], _pre[200005], *ost = _ost + 100000, *pre = _pre+100000; int ilel[100005], ostl[100005], ilep[100005], ostp[100005]; char s[100005]; int _ile[200005], *ile = _ile + 100000; ll wynik[2][100005]; struct Iv { int a=0, b=0; ll podslowa = 0; void exr() { b++; if (ostl[b] < a) podslowa += ile[w[b]]; else podslowa += ilel[b]; ile[w[b]]++; } void exl() { a--; if (ostp[a+1]-1 > b) podslowa += ile[w[a]]; else podslowa += ilep[a+1]; ile[w[a]]++; } void shr() { ile[w[b]]--; if (ostl[b] < a) podslowa -= ile[w[b]]; else podslowa -= ilel[b]; b--; } void shl() { ile[w[a]]--; if (ostp[a+1]-1 > b) podslowa -= ile[w[a]]; else podslowa -= ilep[a+1]; a++; } void przejdz(int c, int d) { while (b < d) exr(); while (a > c) exl(); while (b > d) shr(); while (a < c) shl(); } } przedzial; void obsluz(int a, int b, int u, int v) { int s = (a + b) / 2; int w = min(v, s); ll optw = INF; int najl = 0; for (int i = w; i >= u; i--) { przedzial.przejdz(i-1,s); if (wynik[0][i-1] + przedzial.podslowa < optw) { optw = wynik[0][i-1] + przedzial.podslowa; najl = i; } } wynik[1][s] = optw; if (s > a) obsluz(a, s-1, u, najl); if (s < b) obsluz(s+1, b, najl, v); } int main() { scanf("%d%d %s", &n, &k, s+1); ile[0] = 1; for (int i = 1; i <= n; i++) { w[i] = w[i-1] + (s[i] == '(' ? 1 : -1); if ((ost[w[i]] == 0 && w[i] != 0) || ost[w[i]-1] > ost[w[i]]) { ostl[i] = pre[w[i]] = i; ilel[i] = 0; } else { ostl[i] = pre[w[i]]; ilel[i] = ilel[ost[w[i]]] + 1; } ost[w[i]] = i; } for (int i = -n; i <= n; i++) ost[i] = n+1, pre[i] = n+1; int ww = 0; for (int i = n; i > 0; i--) { ww += (s[i] == ')' ? 1 : -1); if ((ost[ww] == n+1 && ww != 0) || ost[ww-1] < ost[ww]) { ostp[i] = pre[ww] = i; ilep[i] = 0; } else { ostp[i] = pre[ww]; ilep[i] = ilep[ost[ww]] + 1; } ost[ww] = i; } for (int i = 1; i <= n; i++) { przedzial.przejdz(0,i); wynik[0][i] = przedzial.podslowa; } for (int i = 1; i < k; i++) { obsluz(1, n, 1, n); for (int i = 1; i <= n; i++) { wynik[0][i] = wynik[1][i]; wynik[1][i] = 0; } } printf("%lld\n", wynik[0][n]); } |