Submission #1310415

#TimeUsernameProblemLanguageResultExecution timeMemory
1310415ayuxhkumxr22Doktor (COCI17_doktor)C++20
100 / 100
107 ms41952 KiB
/* Author : ayuxh */ #include <bits/stdc++.h> using namespace std; // Speed up C++ I/O void fast_io() { ios_base::sync_with_stdio(false); cin.tie(NULL); } const int MAXN = 500005; int p[MAXN]; // Permutation int pref[MAXN]; // Prefix sum of original fixed points vector<int> groups[2 * MAXN]; // Groups based on i + p[i] void Solve() { int n; if (!(cin >> n)) return; // Read input and build prefix sums of original fixed points for (int i = 1; i <= n; ++i) { cin >> p[i]; pref[i] = pref[i - 1] + (p[i] == i ? 1 : 0); // Group indices by the required center sum (L+R) // For an element at i to be fixed after swap L..R, // it must end up at index p[i]. // Swap maps i -> L+R-i. So we need p[i] = L+R-i => L+R = p[i]+i. groups[p[i] + i].push_back(i); } int max_fixed = -1; int best_L = 1, best_R = 1; // Initial baseline: 0 reversal (L=1, R=1 technically reverses single element) // The loop below will check all valid non-trivial reversals. // We should initialize with the 'no-op' count (which is pref[n]). // But we are maximizing the formula: (New inside) - (Old inside). // The base fixed count is added at the end or we track net change. // Let's track max TOTAL fixed points. // Initialize with Identity transform (L=1, R=1) max_fixed = pref[n]; best_L = p[1]; best_R = p[1]; // Iterate over all possible center sums for (int s = 2; s <= 2 * n; ++s) { if (groups[s].empty()) continue; // Sort candidates by proximity to the center s/2 // We want to expand outwards. // Distance of i from center is |i - s/2|. // Since we are iterating s, s is constant. // We can just sort by index and use two pointers or sort by distance. // Since elements in groups[s] are naturally somewhat ordered if we pushed in order, // let's just use the median-out expansion. // Actually, 'groups' is already sorted by index i because we pushed i=1..N. // The indices are i_1 < i_2 < ... < i_k. // The "center" is s/2. // We need to pair indices that are symmetric? // No, any range [L, R] with L+R=S will cover a subset of these candidates. // The optimal range for a fixed S must have boundaries L and R that are // "close" to the actual candidates to minimize empty space (which costs old fixed points). // Actually, simply iterating through the candidates in the group is enough. // For a fixed S, and a chosen candidate range inside the group (from index u to v in the vector), // The actual array indices are L = groups[s][u] and R = groups[s][v]. // Wait, NO. If we pick range [L, R], we get points for ALL k such that L <= k <= R AND k is in groups[s]. // But we must enforce L + R = S. // So L determines R. R = S - L. // So we can't pick arbitrary u and v. // We pick a "radius". // Let center be C = s/2.0. // For each i in groups[s], radius is |i - C|. // Sort candidates by radius. vector<int>& vec = groups[s]; // Sort by distance to center |2*i - s| sort(vec.begin(), vec.end(), [&](int a, int b){ return abs(2 * a - s) < abs(2 * b - s); }); int current_new_points = 0; for (int i = 0; i < vec.size(); ++i) { int idx = vec[i]; // Expand range to include this candidate // The range must be symmetric around S. // Boundaries are min(idx, s-idx) and max(idx, s-idx). int L = min(idx, s - idx); int R = max(idx, s - idx); // Increment new points count current_new_points++; // Calculate Old Points lost in this range int old_points_lost = pref[R] - pref[L - 1]; int net_fixed = (pref[n] - old_points_lost) + current_new_points; if (net_fixed > max_fixed) { max_fixed = net_fixed; best_L = p[L]; best_R = p[R]; } } } cout << best_L << " " << best_R << "\n"; } int main() { fast_io(); Solve(); 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...
#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...