Seagull Population
The 2025 ICPC Asia Yokohama Regional Contest C
문제
풀이
하한
답 의 하한을 생각해 봅시다.
먼저 번째 날에는 적어도 마리가 있어야 하므로 입니다.
문제가 원형이므로 으로 생각합시다.
번째 날에 도착한 갈매기의 수를 , 떠난 갈매기의 수를 라 하면 입니다.
이므로 입니다. 의 정의상 이므로 입니다.
따라서 입니다.
선형 풀이
만약 문제가 원형이 아니라면 큐를 이용해서 문제를 해결할 수 있습니다.
부터 까지 반복합니다. 여기서는 문제가 선형이므로 으로 생각합시다.
- 이면 를 만큼 큐에 넣습니다.
- 이면 큐에서 개를 꺼내서 각각 끝점을 로 기록하고 출력합니다.
해당 방법으로 풀었을 때의 답을 이라 합시다. 입니다. 원형과 달리 임에 주의합시다.
위 알고리즘에서 구간의 시작이 인 것과 구간의 끝이 인 것을 최대한 합치면 답이 됩니다.
합칠 조건
큐에 넣은 순서대로 갈매기에게 번호를 매겨봅시다.
번 갈매기가 도착한 날을 , 머무른 마지막 날을 라 합시다.
인 갈매기와 인 갈매기를 합치려면 여야 합니다.
최대 매칭
첫 번째 날부터 번째 날까지 도착한 갈매기의 누적 합을 , 번째 날까지 떠난 갈매기의 누적 합을 라 합시다.
번째 날 섬에 있는 갈매기들은 부터 까지의 연속된 번호를 갖습니다. 이 구간의 크기는 정확히 이므로 어떤 두 갈매기의 번호가 이상 차이 난다면 그 두 갈매기는 겹치지 않으므로 합칠 수 있습니다.
이 성질에 의해 개를 서로 합칠 수 있습니다.
부터 까지 번 갈매기와 번 갈매기를 서로 합쳐봅시다.
두 갈매기를 합치려면 여야 합니다.
그런데 이므로 두 갈매기는 항상 구간이 겹치지 않습니다.
따라서 두 갈매기를 합칠 수 있습니다.
최적 증명
입니다.
원형 기준으로 이라 두면 입니다.
의 하한 중 하나인 입니다.
만약 이라면 이 됩니다.
만약 이라면 이 됩니다.
따라서 는 앞서 찾은 하한인 와 같으므로 최적입니다.
코드
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int LIMIT = 2e5;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<ll> b(n + 2);
for (int i = 1; i <= n; i++) cin >> b[i];
ll M = b[1];
ll D = max(0LL, b[1] - b[n]);
for (int i = 2; i <= n; i++) {
M = max(M, b[i]);
D += max(0LL, b[i] - b[i - 1]);
}
ll m = max(M, D);
cout << m << '\n';
if (m > LIMIT) return 0;
queue<int> entry;
vector<pair<int, int>> ans = {{0, 0}};
for (int i = 1; i <= n + 1; i++) {
if (b[i] > b[i - 1]) {
for (int j = 0; j < b[i] - b[i - 1]; j++) entry.push(i);
} else {
for (int j = 0; j < b[i - 1] - b[i]; j++) {
int f = entry.front();
entry.pop();
ans.emplace_back(f, i - 1);
}
}
}
int L = ans.size() - 1;
int k = min({b[1], b[n], L - M});
for (int i = k; i >= 1; i--) {
ans[i].first = ans.back().first;
ans.pop_back();
}
for (int i = 1; i <= L - k; i++) {
auto [s, t] = ans[i];
cout << s << ' ' << t << '\n';
}
return 0;
}댓글
이름과 이메일을 입력해 댓글을 남겨주세요.