Submission #583494

#TimeUsernameProblemLanguageResultExecution timeMemory
583494CyanmondBoarding Passes (BOI22_passes)C++17
100 / 100
587 ms377436 KiB
#include <algorithm> #include <cassert> #include <iostream> #include <limits> #include <string> #include <vector> using namespace std; using i64 = long long int; constexpr i64 inf64 = numeric_limits<i64>::max() / 3; #define ALL(x) (x).begin(), (x).end() #define REP_3(i, l, r) for (int i = (l); i < (r); ++i) #define RVP_3(i, l, r) for (int i = (r - 1); i >= (l); --i) #define REP(i, N) REP_3(i, 0, N) #define RVP(i, N) RVP_3(i, 0, N) void answer(const i64 x) { cout << x / 2; if (x % 2 == 1) cout << ".5" << endl; } template <typename T> void chmin(T &a, const T b) { if (a > b) a = b; } int main() { string s; cin >> s; vector<int> S; for (const int e : s) S.push_back(e - 'A'); const int N = (int)S.size(); const int G = *max_element(ALL(S)) + 1; vector<vector<int>> g_list(G); REP(i, N) g_list[S[i]].push_back(i); vector<vector<i64>> l_v(G, vector<i64>(N + 1)); auto r_v = l_v; vector l_v_w(G, vector(G, vector(N + 1, (i64)0))); auto r_v_w = l_v_w; REP(i, N) { ++l_v[S[i]][i + 1]; ++r_v[S[i]][i]; REP(x, G) { const int p1 = (int)(upper_bound(ALL(g_list[x]), i) - g_list[x].begin()) - 1; const int p2 = (int)(lower_bound(ALL(g_list[x]), i) - g_list[x].begin()); l_v_w[S[i]][x][i + 1] += (int)g_list[x].size() - p1; r_v_w[S[i]][x][i] += p2; } } REP(x, G) { REP(i, N) l_v[x][i + 1] += l_v[x][i]; RVP(i, N) r_v[x][i] += r_v[x][i + 1]; REP(y, G) { REP(i, N) l_v_w[x][y][i + 1] += l_v_w[x][y][i]; RVP(i, N) r_v_w[x][y][i] += r_v_w[x][y][i + 1]; } } auto calc_bound = [&](const int s, const int x) { i64 all_sum = 0; REP(i, G) { if (s & (1 << i)) all_sum += l_v[i][g_list[x].back()] * 2; if (i == x) all_sum += l_v[i][g_list[x].back()]; } int ok = -1, ng = (int)g_list[x].size(); while (ng - ok > 1) { const int m = (ok + ng) / 2; const int p = g_list[x][m]; i64 l_sum = 0, r_sum = 0; REP(i, G) { const i64 l = l_v[i][p + 1], r = r_v[i][p]; if (s & (1 << i)) { l_sum += l * 2; r_sum += r * 2; } if (i == x) { l_sum += l; r_sum += r; } } (l_sum <= r_sum ? ok : ng) = m; } return ok; // time complexity O(G log N) }; auto calc_cost = [&](const int s, const int x, const int m) { i64 ret = 0; const int z = (int)g_list[x].size(); if (m != -1) { const int p = g_list[x][m]; REP(i, G) { if (s & (1 << i)) ret += (l_v_w[i][x][p] - l_v[i][p] * (z - m)) * 2; if (i == x) ret += l_v_w[i][x][p] - l_v[i][p] * (z - m); } } if (m != z - 1) { const int p = g_list[x][m + 1]; REP(i, G) { if (s & (1 << i)) ret += (r_v_w[i][x][p + 1] - r_v[i][p + 1] * (m + 1)) * 2; if (i == x) ret += r_v_w[i][x][p + 1] - r_v[i][p + 1] * (m + 1); } } return ret; }; vector<i64> dp(1 << G, inf64); dp[0] = 0; REP(bit, 1 << G) { REP(x, G) { if (g_list[x].empty()) { chmin(dp[bit | (1 << x)], dp[bit]); continue; } if (bit & (1 << x)) continue; const int m = calc_bound(bit, x); const i64 cost = calc_cost(bit, x, m); chmin(dp[bit | (1 << x)], dp[bit] + cost); } } answer(dp[(1 << G) - 1]); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...