#include <cstdio> #include <ctime> #include <deque> #include <cstring> #include <algorithm> const int N = 100005; const int K = 200; int n, k, pr[N], size = 1, a[N], licz[N / K + 1][N], licz1[N]; unsigned duz[N / K + 1][N]; char s[N]; std::pair<long long, int> d[N]; void init() { for (int i = 0; (i + 1) * K <= n + 1; ++i) { if (i) for (int j = 0; j <= n; ++j) licz[i][j] = licz[i - 1][j]; for (int j = i * K; j < i * K + K; ++j) ++licz[i][a[j]]; } for (int i = 0; (i + 1) * K <= n + 1; ++i) { long long s = 0; for (int j = i * K + K - 1; j >= 0; --j) { s += licz1[a[j]]++; duz[i][j] = s; } for (int i = 0; i <= n; ++i) licz1[i] = 0; } } long long f(int l, int r) { long long ans = 0; if (r - l + 1 <= 2 * K) { for (int i = l; i <= r; ++i) ans += licz1[a[i]]++; for (int i = l; i <= r; ++i) licz1[a[i]] = 0; } else { int bl = l / K, br = r / K; if (bl * K != l) ++bl; if (br * K + K - 1 != r) --br; ans = duz[br][l]; for (int i = l; i < bl * K; ++i) ++licz1[a[i]]; for (int i = br * K + K; i <= r; ++i) { ans += licz1[a[i]]++; ans += licz[br][a[i]] - (bl ? licz[bl - 1][a[i]] : 0); } for (int i = l; i < bl * K; ++i) licz1[a[i]] = 0; for (int i = br * K + K; i <= r; ++i) licz1[a[i]] = 0; } return ans; } int licz2[N]; long long f1(int l, int r) { long long ans = 0; for (int i = l; i <= r; ++i) ans += licz2[a[i]]++; for (int i = l; i <= r; ++i) licz2[a[i]] = 0; return ans; } int call = 0; int lepej(int x, int y) { ++call; int b; int L = y / K, R = (n + 1) / K; while (L < R) { int M = L + R >> 1; if (std::make_pair(d[x].first + duz[M][x], d[x].second) >= std::make_pair(d[y].first + duz[M][y], d[y].second)) R = M; else L = M + 1; } b = R; int bx = x / K; if (bx * K != x) ++bx; int by = y / K; if (by * K != y) ++by; if (b > y / K) { for (int i = x; i < bx * K; ++i) ++licz1[a[i]]; for (int i = y; i < by * K; ++i) --licz1[a[i]]; long long ws = d[x].first - d[y].first + duz[b - 1][x] - duz[b - 1][y]; int p; for (p = b * K; p <= n; ++p) { ws += licz1[a[p]]; ws += -(bx ? licz[bx - 1][a[p]] : 0) + (by ? licz[by - 1][a[p]] : 0); if (ws > 0 || !ws && d[x].second >= d[y].second) { for (int i = x; i < bx * K; ++i) licz1[a[i]] = 0; for (int i = y; i < by * K; ++i) licz1[a[i]] = 0; return p; } } for (int i = x; i < bx * K; ++i) licz1[a[i]] = 0; for (int i = y; i < by * K; ++i) licz1[a[i]] = 0; return p; } if (y - x + 1 <= 2 * K) { long long ws = d[x].first - d[y].first; for (int i = x; i <= y; ++i) ws += licz1[a[i]]++; --licz1[a[y]]; int p; for (p = y + 1; p <= n; ++p) { ws += licz1[a[p]]; if (ws > 0 || !ws && d[x].second >= d[y].second) { for (int i = x; i <= y; ++i) licz1[a[i]] = 0; return p; } } for (int i = x; i <= y; ++i) licz1[a[i]] = 0; return p; } if (b * K + K - 1 == y) return y + 1; long long ws = d[x].first - d[y].first; for (int i = x; i < bx * K; ++i) ++licz1[a[i]]; ws += duz[b - 1][x]; for (int i = b * K; i <= y; ++i) { ws += licz1[a[i]]++; ws += licz[b - 1][a[i]] - (bx ? licz[bx - 1][a[i]] : 0); } --licz1[a[y]]; int p; for (p = y + 1; p <= n; ++p) { ws += licz1[a[p]]; ws += licz[b - 1][a[p]] - (bx ? licz[bx - 1][a[p]] : 0); if (ws > 0 || !ws && d[x].second >= d[y].second) { for (int i = x; i < bx * K; ++i) licz1[a[i]] = 0; for (int i = b * K; i <= y; ++i) licz1[a[i]] = 0; return p; } } for (int i = x; i < bx * K; ++i) licz1[a[i]] = 0; for (int i = b * K; i <= y; ++i) licz1[a[i]] = 0; return n + 1; } void run(long long C) { d[0] = std::make_pair(0, 0); std::deque<std::pair<int, int> > dq; dq.push_back(std::make_pair(0, 0)); for (int i = 1; i <= n; ++i) { while (dq.size() > 1 && dq[1].second <= i) dq.pop_front(); d[i] = std::make_pair(d[dq[0].first].first + C + f(dq[0].first, i), d[dq[0].first].second + 1); while (!dq.empty()) { int l = lepej(dq.back().first, i); if (dq.back().second >= l) dq.pop_back(); else { dq.push_back(std::make_pair(i, l)); break; } } if (dq.empty()) dq.push_back(std::make_pair(i, 0)); } call = 0; } int main() { //n = 100000; //k = 500; scanf("%d%d", &n, &k); //for (int i = 0; i < n; ++i) s[i] = i & 1 ? ')' : '('; scanf("%s", s); //for (int i = 0; i < n; ++i) s[i] = rand() & 1 ? '(' : ')'; int cur = 0; pr[0] = -1; for (int i = 0; i <= n; ++i) { a[i] = cur; if (i < n) { if (s[i] == '(') { pr[size] = cur; cur = size++; } else { if (pr[cur] == -1) { pr[size] = -1; pr[cur] = size++; } cur = pr[cur]; } } } init(); long long l = 0, r = (long long)N * N; while (l < r) { long long m = l + r >> 1; run(m); if (d[n].second <= k) r = m; else l = m + 1; } run(r); printf("%lld\n", d[n].first - (long long)k * r); //fprintf(stderr, "%lf\n", (double)clock() / CLOCKS_PER_SEC); 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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | #include <cstdio> #include <ctime> #include <deque> #include <cstring> #include <algorithm> const int N = 100005; const int K = 200; int n, k, pr[N], size = 1, a[N], licz[N / K + 1][N], licz1[N]; unsigned duz[N / K + 1][N]; char s[N]; std::pair<long long, int> d[N]; void init() { for (int i = 0; (i + 1) * K <= n + 1; ++i) { if (i) for (int j = 0; j <= n; ++j) licz[i][j] = licz[i - 1][j]; for (int j = i * K; j < i * K + K; ++j) ++licz[i][a[j]]; } for (int i = 0; (i + 1) * K <= n + 1; ++i) { long long s = 0; for (int j = i * K + K - 1; j >= 0; --j) { s += licz1[a[j]]++; duz[i][j] = s; } for (int i = 0; i <= n; ++i) licz1[i] = 0; } } long long f(int l, int r) { long long ans = 0; if (r - l + 1 <= 2 * K) { for (int i = l; i <= r; ++i) ans += licz1[a[i]]++; for (int i = l; i <= r; ++i) licz1[a[i]] = 0; } else { int bl = l / K, br = r / K; if (bl * K != l) ++bl; if (br * K + K - 1 != r) --br; ans = duz[br][l]; for (int i = l; i < bl * K; ++i) ++licz1[a[i]]; for (int i = br * K + K; i <= r; ++i) { ans += licz1[a[i]]++; ans += licz[br][a[i]] - (bl ? licz[bl - 1][a[i]] : 0); } for (int i = l; i < bl * K; ++i) licz1[a[i]] = 0; for (int i = br * K + K; i <= r; ++i) licz1[a[i]] = 0; } return ans; } int licz2[N]; long long f1(int l, int r) { long long ans = 0; for (int i = l; i <= r; ++i) ans += licz2[a[i]]++; for (int i = l; i <= r; ++i) licz2[a[i]] = 0; return ans; } int call = 0; int lepej(int x, int y) { ++call; int b; int L = y / K, R = (n + 1) / K; while (L < R) { int M = L + R >> 1; if (std::make_pair(d[x].first + duz[M][x], d[x].second) >= std::make_pair(d[y].first + duz[M][y], d[y].second)) R = M; else L = M + 1; } b = R; int bx = x / K; if (bx * K != x) ++bx; int by = y / K; if (by * K != y) ++by; if (b > y / K) { for (int i = x; i < bx * K; ++i) ++licz1[a[i]]; for (int i = y; i < by * K; ++i) --licz1[a[i]]; long long ws = d[x].first - d[y].first + duz[b - 1][x] - duz[b - 1][y]; int p; for (p = b * K; p <= n; ++p) { ws += licz1[a[p]]; ws += -(bx ? licz[bx - 1][a[p]] : 0) + (by ? licz[by - 1][a[p]] : 0); if (ws > 0 || !ws && d[x].second >= d[y].second) { for (int i = x; i < bx * K; ++i) licz1[a[i]] = 0; for (int i = y; i < by * K; ++i) licz1[a[i]] = 0; return p; } } for (int i = x; i < bx * K; ++i) licz1[a[i]] = 0; for (int i = y; i < by * K; ++i) licz1[a[i]] = 0; return p; } if (y - x + 1 <= 2 * K) { long long ws = d[x].first - d[y].first; for (int i = x; i <= y; ++i) ws += licz1[a[i]]++; --licz1[a[y]]; int p; for (p = y + 1; p <= n; ++p) { ws += licz1[a[p]]; if (ws > 0 || !ws && d[x].second >= d[y].second) { for (int i = x; i <= y; ++i) licz1[a[i]] = 0; return p; } } for (int i = x; i <= y; ++i) licz1[a[i]] = 0; return p; } if (b * K + K - 1 == y) return y + 1; long long ws = d[x].first - d[y].first; for (int i = x; i < bx * K; ++i) ++licz1[a[i]]; ws += duz[b - 1][x]; for (int i = b * K; i <= y; ++i) { ws += licz1[a[i]]++; ws += licz[b - 1][a[i]] - (bx ? licz[bx - 1][a[i]] : 0); } --licz1[a[y]]; int p; for (p = y + 1; p <= n; ++p) { ws += licz1[a[p]]; ws += licz[b - 1][a[p]] - (bx ? licz[bx - 1][a[p]] : 0); if (ws > 0 || !ws && d[x].second >= d[y].second) { for (int i = x; i < bx * K; ++i) licz1[a[i]] = 0; for (int i = b * K; i <= y; ++i) licz1[a[i]] = 0; return p; } } for (int i = x; i < bx * K; ++i) licz1[a[i]] = 0; for (int i = b * K; i <= y; ++i) licz1[a[i]] = 0; return n + 1; } void run(long long C) { d[0] = std::make_pair(0, 0); std::deque<std::pair<int, int> > dq; dq.push_back(std::make_pair(0, 0)); for (int i = 1; i <= n; ++i) { while (dq.size() > 1 && dq[1].second <= i) dq.pop_front(); d[i] = std::make_pair(d[dq[0].first].first + C + f(dq[0].first, i), d[dq[0].first].second + 1); while (!dq.empty()) { int l = lepej(dq.back().first, i); if (dq.back().second >= l) dq.pop_back(); else { dq.push_back(std::make_pair(i, l)); break; } } if (dq.empty()) dq.push_back(std::make_pair(i, 0)); } call = 0; } int main() { //n = 100000; //k = 500; scanf("%d%d", &n, &k); //for (int i = 0; i < n; ++i) s[i] = i & 1 ? ')' : '('; scanf("%s", s); //for (int i = 0; i < n; ++i) s[i] = rand() & 1 ? '(' : ')'; int cur = 0; pr[0] = -1; for (int i = 0; i <= n; ++i) { a[i] = cur; if (i < n) { if (s[i] == '(') { pr[size] = cur; cur = size++; } else { if (pr[cur] == -1) { pr[size] = -1; pr[cur] = size++; } cur = pr[cur]; } } } init(); long long l = 0, r = (long long)N * N; while (l < r) { long long m = l + r >> 1; run(m); if (d[n].second <= k) r = m; else l = m + 1; } run(r); printf("%lld\n", d[n].first - (long long)k * r); //fprintf(stderr, "%lf\n", (double)clock() / CLOCKS_PER_SEC); return 0; } |