제출 #1302167

#제출 시각아이디문제언어결과실행 시간메모리
1302167itachi_godRope (JOI17_rope)C++20
0 / 100
1 ms572 KiB
/** * JOI 2016/2017 Final Round - Task 5: Rope * Solution based on Pair Parity Observation. * * Logic: * The folding process partitions the rope into adjacent pairs that are merged. * We analyze adjacent pairs in different alignments (starting at index 0 or 1). * We aim to maximize matches for a Target Color C and an optimal Partner Color Y. */ #include <iostream> #include <vector> #include <algorithm> #include <map> using namespace std; const int INF = 1e9; // Global variables to store frequencies and answers int N, M; vector<int> ar; vector<int> ans; vector<int> app; // Total appearance count of each color vector<int> d; // Colors sorted by frequency // Updates the answer for color 'a' with a new minimum cost 'b' void chmin(int& a, int b) { if (b < a) a = b; } // Solver function for a specific sub-segment of the rope // n: length of the segment to consider // offset: starting index in the global array 'ar' // L, R: Boundary colors (leftover cords) that are NOT part of pairs // (passed as -1 if they don't exist in the current cut) void solve(int n, int offset, int L, int R) { // If n is odd, one element is left unpaired inside the range. // The passed L and R account for boundary "singletons". // 1. Identify pairs (u, v) in this alignment vector<pair<int, int>> ps; ps.reserve(n / 2); for (int i = 0; i < n - 1; i += 2) { int u = ar[offset + i]; int v = ar[offset + i + 1]; if (u > v) swap(u, v); ps.push_back({u, v}); } // Sort pairs to count unique overlaps efficiently sort(ps.begin(), ps.end()); // Unique the pairs to iterate distinct combinations vector<pair<int, int>> unique_ps = ps; unique_ps.erase(unique(unique_ps.begin(), unique_ps.end()), unique_ps.end()); // Count occurrences of each specific pair vector<int> pscnt(unique_ps.size(), 0); // Use lower_bound to find index in unique_ps for (size_t i = 0; i < ps.size(); ++i) { int idx = lower_bound(unique_ps.begin(), unique_ps.end(), ps[i]) - unique_ps.begin(); pscnt[idx]++; } // 2. Optimization 1: Calculate cost based on adjacent pairs found for (size_t i = 0; i < unique_ps.size(); ++i) { int u = unique_ps[i].first; int v = unique_ps[i].second; // Cost formula explanation: // We want to keep all 'u' and all 'v'. // Total instances = app[u] + app[v]. // However, pscnt[i] is the number of times u and v appear as a specific merged pair. // In those merged pairs, we gain +1 match total (either u or v matches), // whereas app[u]+app[v] counts +2. So we subtract pscnt[i] to correct the gain. // Total Gain = app[u] + app[v] - pscnt[i]. // Cost = Total_Rope_Length - Total_Gain. // Note: The rope length for cost calculation is the original N. int val = N - (app[u] + app[v] - pscnt[i]); chmin(ans[u], val); chmin(ans[v], val); } // 3. Optimization 2: Fallback for high-frequency colors that might NOT be adjacent // We try to pair color 'i' with the most frequent color 'j' such that // the pair (i, j) was NOT handled in the loop above (i.e., not strictly adjacent). // We iterate through colors sorted by frequency (descending) for (int i = 0; i < M; ++i) { int color_u = d[i]; // Find the best partner color_v (d[j]) int j = 0; while (j < M) { int color_v = d[j]; if (color_u == color_v) { j++; continue; } // Check if this pair (u, v) exists in the current adjacent pairing. // If it does, we already processed the optimal case for it in step 2. // If it does NOT, the overlap is 0, so Gain = app[u] + app[v]. // We check existence using binary search on unique_ps. int mn = min(color_u, color_v); int mx = max(color_u, color_v); if (binary_search(unique_ps.begin(), unique_ps.end(), make_pair(mn, mx))) { j++; // This pair was adjacent, so handled above. Skip. } else { // Found best non-adjacent partner. int val = N - (app[color_u] + app[color_v]); chmin(ans[color_u], val); chmin(ans[color_v], val); break; // Since d is sorted by frequency, the first valid j is the best. } } } } int main() { // Fast I/O ios_base::sync_with_stdio(false); cin.tie(NULL); if (!(cin >> N >> M)) return 0; if (M == 1) { cout << "0\n"; return 0; } ar.resize(N); app.assign(M, 0); ans.assign(M, INF); for (int i = 0; i < N; ++i) { cin >> ar[i]; ar[i]--; // Convert to 0-based index app[ar[i]]++; } // Prepare 'd' array: colors sorted by frequency descending d.resize(M); for (int i = 0; i < M; ++i) d[i] = i; sort(d.begin(), d.end(), [&](int a, int b) { return app[a] > app[b]; }); // We try 4 configurations to cover all alignment parities and boundary conditions // 1. Full array, starting at 0 solve(N, 0, -1, -1); // 2. Skip first element, starting at 1 (Shifted alignment) solve(N - 1, 1, ar[0], -1); // 3. Skip last element (Alignment starting at 0, but N-1 length) solve(N - 1, 0, -1, ar[N - 1]); // 4. Skip first and last (Shifted alignment, N-2 length) solve(N - 2, 1, ar[0], ar[N - 1]); for (int i = 0; i < M; ++i) { cout << ans[i] << "\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...
#Verdict Execution timeMemoryGrader output
Fetching results...