Submission #788491

#TimeUsernameProblemLanguageResultExecution timeMemory
788491hugo_pmChorus (JOI23_chorus)C++17
0 / 100
1 ms468 KiB
#include <bits/stdc++.h> #define int long long using namespace std; #define all(v) (v).begin(), (v).end() #define rall(v) (v).rbegin(), (v).rend() #define rep(i, a, b) for(int i = (a); i < (b); i++) #define sz(v) ((int)((v).size())) template<typename T> void chmax(T &x, const T &v) { if (x < v) x = v; } template<typename T> void chmin(T &x, const T &v) { if (x > v) x = v; } using pii = pair<int, int>; using vi = vector<int>; string to_string(string s) { return s; } template <typename T> string to_string(T v) { bool first = true; string res = "["; for (const auto &x : v) { if (!first) res += ", "; first = false; res += to_string(x); } res += "]"; return res; } void dbg_out() { cout << endl; } template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cout << ' ' << to_string(H); dbg_out(T...); } #ifdef DEBUG #define dbg(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__) #else #define dbg(...) #endif const int INF = 1e12; struct _Line { mutable int k, m, p; bool operator<(const _Line& o) const { return k < o.k; } bool operator<(int x) const { return p < x; } }; struct _LineContainer : multiset<_Line, less<>> { // (for doubles, use inf = 1/.0, div(a,b) = a/b) static const int inf = LLONG_MAX; int div(int a, int b) { // floored division return a / b - ((a ^ b) < 0 && a % b); } bool isect(iterator x, iterator y) { if (y == end()) return x->p = inf, 0; if (x->k == y->k) x->p = x->m > y->m ? inf : -inf; else x->p = div(y->m - x->m, x->k - y->k); return x->p >= y->p; } void add(int k, int m) { auto z = insert({k, m, 0}), y = z++, x = y; while (isect(y, z)) z = erase(z); if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); while ((y = x) != begin() && (--x)->p >= y->p) isect(x, erase(y)); } int queryMax(int x) { assert(!empty()); auto l = *lower_bound(x); return l.k * x + l.m; } }; struct LineContainer { _LineContainer fs; void add (int k, int m) { // kx+m // -f(x) = -(kx+m) = (-k)x + (-m) fs.add(-k, -m); } int min(int x) { return -fs.queryMax(x); } }; int N, K; string S; // ferme[i] = nombre d'ouvrants avant Fi vector<int> ouvre, ferme; vector<int> cumuFerme; int coutExclus(int left, int right) { if (left >= right) { return 0; } int projExclus = min(right, ouvre[right-1]); if (projExclus <= left) return 0; return (projExclus - left)*(right) - (cumuFerme[projExclus] - cumuFerme[left]); } signed main() { ios::sync_with_stdio(false); cin.tie(0); cin >> N >> K >> S; { int curOuvre = 0, curFerme = 0; cumuFerme.push_back(0); for (char c : S) { if (c == 'A') { ++curOuvre; ouvre.push_back(curFerme); } else { ++curFerme; ferme.push_back(curOuvre); cumuFerme.push_back(cumuFerme.back() + curOuvre); } } } vector<int> old(N+1, INF), now; old[N] = 0; rep(nbCoup, 1, K+1) { now.assign(N+1, INF); LineContainer cont; // [J EXCLUS] // gright(left) = (projExclus - left)*(right) - (cumuFerme[projExclus] - cumuFerme[left]) // gj(x) = (pj - x)*j - (cf[pj] - cf[left]) // gj(x) = -jx + (j*pj - cf[pj]) + cf[x] // mx + p + terme fixe auto getWithFix = [&] (int x) { return cont.min(x) + cumuFerme[x]; }; auto proj = [&] (int j) { return min(j, ouvre[j-1]); }; auto add = [&] (int j) { int pj = proj(j); cont.add(-j, old[j] + j*pj - cumuFerme[pj]); }; int jToAdd = N; for (int left = N-1; left >= 0; --left) { while (jToAdd > 0 && left <= proj(jToAdd)) { add(jToAdd--); } chmin(now[left], getWithFix(left)); if (jToAdd > 0) { chmin(now[left], old[jToAdd] + coutExclus(left, jToAdd)); } } old = now; } cout << old[0] << '\n'; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...