제출 #833775

#제출 시각아이디문제언어결과실행 시간메모리
833775CSQ31Chorus (JOI23_chorus)C++17
100 / 100
1469 ms91604 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 = 3e12; struct Line { int m, p, cnt; pii eval(int x) const { return {m*x+p, cnt}; } }; struct LineContainer { vector<Line> fs; int front = 0; bool bad(Line a, Line b, Line c) { // (cp-ap)/(am-cm) < (bp-ap)/(am-bm) int v1 = (c.p - a.p) * (a.m - b.m); int v2 = (b.p - a.p) * (a.m - c.m); return v1 >= v2; } void add (Line l) { int szFs = sz(fs); while (szFs >= front+2 && bad(fs[szFs-2], fs[szFs-1], l)) { fs.pop_back(), --szFs; } fs.push_back(l); } pii min(int x) { if (fs.empty()) return {INF, INF}; chmin(front, sz(fs)-1); while (front+1 < sz(fs) && fs[front].eval(x) >= fs[front+1].eval(x)) { ++front; } return fs[front].eval(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); } } } auto calc = [&] (int lambda) -> pii { vector<pii> dp(N+1, {INF, INF}); dp[N] = {0, 0}; 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 proj = [&] (int j) { return min(j, ouvre[j-1]); }; auto add = [&] (int j) { int pj = proj(j); // add -10 -9 -8.. pente croissante cont.add({-j, dp[j].first + j*pj - cumuFerme[pj], dp[j].second}); }; int jToAdd = N; for (int left = N-1; left >= 0; --left) { while (jToAdd > 0 && left <= min(proj(jToAdd), jToAdd-1)) { add(jToAdd--); } if (true) { // min(10) min(9) .. x décroissant pii prop = cont.min(left); chmin(dp[left], make_pair( prop.first + cumuFerme[left] + lambda, prop.second + 1 )); } if (jToAdd > 0) { chmin(dp[left], make_pair( dp[jToAdd].first + coutExclus(left, jToAdd) + lambda, dp[jToAdd].second + 1 )); } } return dp[0]; }; int lo = 0, hi = INF; while (lo <= hi) { int mid = (lo+hi) / 2; if(calc(mid).second > K) { lo = mid+1; } else { hi = mid-1; } } //assert(lo == hi); int lambda = lo; auto [score, groupsMade] = calc(lambda); assert(groupsMade <= K); cout << score - lambda*K << '\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...