Submission #1276768

#TimeUsernameProblemLanguageResultExecution timeMemory
1276768LudisseyBoarding Passes (BOI22_passes)C++20
100 / 100
667 ms91944 KiB
#include <bits/stdc++.h>
#define int long long
#define sz(a) (int)a.size()
#define all(a) a.begin(), a.end()
 
using namespace std;
unordered_map<char,int> um;
vector<vector<vector<int>>> cnt;
vector<vector<int>> val;
vector<int> dp;
vector<vector<int>> grp;
int n,g;

int calc(int l, int _g, int mask){
    int lft=((l+1)*l)/2;
    int r=(sz(grp[_g])-l-1);
    int rgt=((r-1)*r)/2;
    if(l>=0){
        for (int i = 0; i < g; i++)
        {
            if(mask&(1<<i)) lft+=cnt[grp[_g][l]][i][0]*2;
        }
    }
    if(l+1<sz(grp[_g])){
        for (int i = 0; i < g; i++)
        {
            if(mask&(1<<i)) rgt+=cnt[grp[_g][l+1]][i][1]*2;
        }
    }
    return lft+rgt;
}

int dfs(int mask){
    if(dp[mask]!=-1) return dp[mask];
    dp[mask]=1e18;
    int mnI=0;
    for (int i = 0; i < g; i++)
    {
        if(mask&(1<<i)) {
            int r=dfs(mask-(1<<i))+val[i][mask-(1<<i)];
            if(r<dp[mask]) mnI=i;
            dp[mask]=min(dp[mask],r);
        }
    }
    //cerr << mask << "-> " << mnI << " = " << dp[mask] << "\n";
    return dp[mask];
}

signed main() {
    ios_base::sync_with_stdio(false); cin.tie(nullptr);
    string s; cin >> s;
    n=sz(s);
    vector<int> a(n);
    for (int i = 0; i < n; i++)
    {
        if(um.find(s[i])==um.end()) um[s[i]]=sz(um);
        a[i]=um[s[i]];
    }
    g=sz(um);
    val.resize(g, vector<int>((1<<g),1e18));
    dp.resize((1<<g),-1);
    cnt.resize(n, vector<vector<int>>(g, vector<int>(2,0)));
    grp.resize(g);
    for (int i = 0; i < n; i++) grp[a[i]].push_back(i);
    
    for (int i = 0; i < g; i++)
    {
        for (int j = 0; j < g; j++)
        {
            int sm=0;
            int sm_cnt=0;
            for (int k = 0; k < n; k++)
            {
                if(a[k]==i) cnt[k][j][0]=sm+sm_cnt, sm_cnt+=sm;
                if(a[k]==j) sm++;
            }
            sm=0;
            sm_cnt=0;
            for (int k = n-1; k >= 0; k--)
            {
                if(a[k]==i) cnt[k][j][1]=sm+sm_cnt, sm_cnt+=sm;
                if(a[k]==j) sm++;
            }
        }
    }

    for (int i = 0; i < g; i++)
    {
        for (int mask = 0; mask < (1<<g); mask++)
        {
            if(mask&(1<<i)) continue;
            int l=-1, r=sz(grp[i])-1;
            while(r-l>2){
                int mid1=l+(r-l)/3;
                int mid2=r-(r-l)/3;
                if(calc(mid1, i, mask)<calc(mid2, i, mask)){
                    r=mid2;
                }else{
                    l=mid1;
                }
            }
            for (int j = l; j <= r; j++)
            {
                val[i][mask]=min(val[i][mask], calc(j, i, mask));
            }
        }
    }
    dp[0]=0;
    long double ret=(long double)dfs((1<<g)-1)/(long double)2;
    cout << fixed << setprecision(1) << (long double)ret << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...