/**
* Problem: COCI 2017/2018 Round 2 - Doktor
* Logic: Center Expansion / Contribution Technique
* Complexity: O(N log N)
*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 500005;
int N;
int A[MAXN];
int pref[MAXN]; // Prefix sum of original fixed points
vector<int> candidates[2 * MAXN]; // Group indices by sum (A[i] + i)
// Helper to get original fixed points in range [L, R]
int get_original_fixed(int L, int R) {
if (L > R) return 0;
return pref[R] - pref[L - 1];
}
int main() {
// Fast I/O
ios_base::sync_with_stdio(false);
cin.tie(NULL);
if (!(cin >> N)) return 0;
for (int i = 1; i <= N; i++) {
cin >> A[i];
}
// 1. Precompute Original Fixed Points
for (int i = 1; i <= N; i++) {
pref[i] = pref[i - 1] + (A[i] == i ? 1 : 0);
}
// 2. Group candidates by invariant sum S = A[i] + i
// Potential sums range from 1+1=2 to N+N=2N
for (int i = 1; i <= N; i++) {
int S = A[i] + i;
candidates[S].push_back(i);
}
int best_gain = -1e9; // Initialize with a very low value
int best_L = 1;
int best_R = 1;
// 3. Process each Sum group
for (int S = 2; S <= 2 * N; S++) {
if (candidates[S].empty()) continue;
// We need to process nested intervals [L, R] where L + R = S.
// The interval is defined by L. The closer L is to S/2, the smaller the interval.
// We collect all L boundaries implied by the candidates.
// For a candidate i, the minimal interval covering it is [min(i, S-i), max(i, S-i)].
// Let's store the 'L' coordinate of these minimal intervals.
vector<int> L_coords;
for (int idx : candidates[S]) {
int L = min(idx, S - idx);
L_coords.push_back(L);
}
// Sort L_coords descending.
// Why? We start from the center (largest L) and expand outwards (smaller L).
// Largest L corresponds to the smallest interval [L, S-L].
sort(L_coords.begin(), L_coords.end(), greater<int>());
int current_new_fixed = 0;
// Iterate through unique L coordinates (distinct nested shells)
for (size_t k = 0; k < L_coords.size(); ) {
int curr_L = L_coords[k];
int curr_R = S - curr_L;
// Add all candidates that have this specific L boundary
// (There might be multiple, e.g., i and S-i)
int count_same_L = 0;
while (k < L_coords.size() && L_coords[k] == curr_L) {
count_same_L++;
k++;
}
current_new_fixed += count_same_L;
// Calculate Net Gain for interval [curr_L, curr_R]
// Gain = (New Fixed Points) - (Original Fixed Points disrupted)
int original_loss = get_original_fixed(curr_L, curr_R);
int net_gain = current_new_fixed - original_loss;
if (net_gain > best_gain) {
best_gain = net_gain;
best_L = curr_L;
best_R = curr_R;
}
}
}
// Output the VALUES on the cards at the best range boundaries
cout << A[best_L] << " " << A[best_R] << endl;
return 0;
}
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |