Submission #1366592

#TimeUsernameProblemLanguageResultExecution timeMemory
1366592OwstinBoarding Passes (BOI22_passes)C++20
100 / 100
179 ms31968 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
#define pb push_back
#define all(x) begin(x), end(x)
#define space " "
#define TEST_CASES int a; cin >> a; for (int i = 0; i < a; i++) {solve(); cout << endl;}
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
template<typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());

void solve() {
    string s; cin >> s; int n = s.size();
    vector<int> vec(n);
    vector<vector<int>> alph(15);
    for (int i = 0; i < n; i++) {
        vec[i] = s[i] - 'A';
        alph[vec[i]].pb(i);
    }
    vector<vector<vector<ll>>> lefts(15, vector<vector<ll>>(15));
    vector<vector<vector<ll>>> rights(15, vector<vector<ll>>(15));
    for (int i = 0; i < 15; i++) {
        ll curr = 0; ll curr2 = 0;
        for (int j = 0; j < n; j++) {
            if (vec[j] == i) {
                curr++;
            }
            lefts[vec[j]][i].pb(curr + (lefts[vec[j]][i].empty() ? 0 : lefts[vec[j]][i].back()));
        }
        for (int j = n - 1; j >= 0; j--) {
            if (vec[j] == i) {
                curr2++;
            }
            rights[vec[j]][i].pb(curr2 + (rights[vec[j]][i].empty() ? 0 : rights[vec[j]][i].back()));
        }
    }
    vector<ld> dp(1 << 15, (ll)n * (n - 1) / 2);
    auto check = [&] (int subset, int letter, int split) -> ld {
        ll num = alph[letter].size();
        ld res = 0;
        for (int i = 0; i < 15; i++) {
            if (subset & 1 << i) {
                res += (split == -1 ? 0 : lefts[letter][i][split]) +
                    (split != num - 1 ? rights[letter][i][num - split - 2] : 0);
            }
        }
        res += (ld)split * (split + 1) / 4 + (ld)(num - split - 1) * (num - split - 2) / 4;
        return res;
    };
    dp[0] = 0;
    for (int i = 1; i < 1 << 15; i++) {
        for (int j = 0; j < 15; j++) {
            if (i & 1 << j) {
                if (!alph[j].empty()) {
                    int lo = -1; int hi = alph[j].size() - 1;
                    while (lo < hi) {
                        int mid = (lo + hi) / 2; int next = mid + 1;
                        if (lo == -1 && hi == 0) {
                            mid = -1; next = 0;
                        }
                        ld r1 = check(i ^ 1 << j, j, mid); ld r2 = check(i ^ 1 << j, j, next);
                        if (r2 <= r1) {
                            lo = next;
                        }
                        else {
                            hi = mid;
                        }
                    }
                    dp[i] = min(dp[i], dp[i ^ 1 << j] + check(i ^ 1 << j, j , lo));
                }
                else {
                    dp[i] = min(dp[i], dp[i ^ 1 << j]);
                }
            }
        }
    }
    cout << fixed << setprecision(10);
    cout << dp.back();
}

int main() {
    FAST_IO;
    //freopen("lightsout.in", "r", stdin);
    //freopen("lightsout.out", "w", stdout);
    //TEST_CASES;
    solve(); cout << endl;
    /*int a; cin >> a;
    for (int i = 1; i <= a; i++){
        cout << "Case #" << i << ": ";
        solve();
        cout << endl;
    }*/
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...