제출 #1181069

#제출 시각아이디문제언어결과실행 시간메모리
1181069tamyteBoarding Passes (BOI22_passes)C++20
100 / 100
191 ms36716 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main(){
    // random_device rd;
    // mt19937 rng(rd());
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 	string s;
 	cin >> s;
 	int n = s.size();
 	vector<vector<int>> points(15);
 	vector<int> pool;
 	for (int i = 0; i < n; ++i) {
 		int j = s[i] - 'A';
 		pool.push_back(j);
 	}
 	sort(begin(pool), end(pool));
 	pool.erase(unique(begin(pool), end(pool)), end(pool));
 	map<char, int> mp;
 	for (int i = 0; i < pool.size(); ++i) {
 		mp[(pool[i] + 'A')] = i;
 	}
 	vector<vector<int>> cnt(15, vector<int>(n + 1));
 	for (int i = 0; i < n; ++i) {
 		points[mp[s[i]]].push_back(i);
 		for (int j = 0; j < 15; ++j) {
 			cnt[j][i + 1] = cnt[j][i] + (j == mp[s[i]]);
 		}
 	}
 	// for (int j = 0; j < 2; ++j) {
 		// for (int i = 0; i < n; ++i) {
 			// cout << cnt[j][i] << " ";
 		// }
 		// cout << endl;
 	// }
 	int k = pool.size();
 	vector<vector<double>> nxt((1 << k), vector<double>(k));
 	// cerr << "BEGIN:\n";
 	for (int i = 0; i < k; ++i) {
 		// cerr << "A\n";
 		auto v = points[i];
 		vector<vector<ll>> L(k, vector<ll>(v.size())), R(k, vector<ll>(v.size()));
 		for (int j = 0; j < k; ++j) {
 			for (int l = 0; l < v.size(); ++l) {
 				L[j][l] = cnt[j][v[l]];
 				if (l > 0) L[j][l] += L[j][l - 1];
 			}
 			for (int l = v.size() - 1; l >= 0; --l) {
 				R[j][l] = cnt[j][n] - cnt[j][v[l] + 1];
 				if (l + 1 < v.size()) R[j][l] += R[j][l + 1];
 			}
 		}
 		// cerr << "B\n";
 		for (int j = 0; j < (1 << k); ++j) {
 			if (j >> i & 1) continue;
 			auto calc = [&](ll l) -> double {
 				double res = 0;
 				for (int x = 0; x < k; ++x) {
 					if (j >> x & 1) {
 						if (l > 0) res += L[x][l - 1];
 						if (l < v.size()) res += R[x][l];
 					}
 				}
 				res += 1.0 * l * (l - 1) / 4.0;
 				ll r = v.size() - l;
 				res += 1.0 * r * (r - 1) / 4.0;
 				return res;
 			};
 			int l = 0, r = v.size();
 			while (l < r) {
 				int mid = (l + r) / 2;
 				if (calc(mid) > calc(mid + 1)) {
 					l = mid + 1;
 				} else {
 					r = mid;
 				}
 			}
 			nxt[j][i] = calc(l);
 		}
 		// cerr << "C\n";
 	}
 	// cerr << "END\n";
 	vector<double> dp((1 << k), 1e15);
 	dp[0] = 0;
 	for (int mask = 0; mask < (1 << k); ++mask) {
 		if (dp[mask] == 1e15) continue;
 		for (int j = 0; j < k; ++j) {
 			if (mask >> j & 1) continue;
 			// cout << "NOW = " << char(j + 'A') << "\n";
 			double ndp = dp[mask] + nxt[mask][j];
 			dp[mask | (1 << j)] = min(dp[mask | (1 << j)], ndp);
 		}
 	}
 	cout << fixed << setprecision(10) << dp[(1 << k) - 1] << endl;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...