公式

B - レ/V 解説 by en_translator


This problem can be solved by appropriately implementing the operations described in the Problem Statement.
The problem is how to find the connecting component containing the minimum integer \(x\). While this can be found with a Disjoint Set Union or BFS (Breadth-First Search), we can simply use the property of “レ” marks. That is, the graph \(G\) in the Problem Statement has a form like 1-2-3-4, 5, 6, 7-8-9-10, where consecutive integers are connected, so the connected components can be detected by extending the segment as long as it is connected to the minimum integer.

Therefore, it can be computed by the following procedure.

  • Let \(\mathrm{ans}\) be an array to manage the answer, which is initially empty.
  • Also, let \(L = 1\), which represents the minimum unvisited integer.
  • While \(L \leq N\), repeat the following:
    • Let \(R = L\). While there is a “レ” mark between \(R\) and \((R+1)\), increment \(R\) by one.
    • Since \(L, L+1, \dots\), and \(R\) forms a connected component, add integers between \(L\) and \(R\) to \(\mathrm{ans}\) in descending order.
    • Now that we have visited up to \(R\), let \(L \gets R + 1\).
  • The sequence \(\mathrm{ans}\) is the answer when the loop above has finished.

With a proper implementation, this procedure runs in an \(\mathrm{O}(N^2)\) or \(\mathrm{O}(N)\) time, which is fast enough.

  • Sample code (C++)
#include <iostream>
#include <vector>
using namespace std;

int main() {
  int N, M;
  cin >> N >> M;
  vector<int> a(M);
  for (auto& x : a) cin >> x;
  vector<int> re(N + 1);
  for (auto& x : a) re[x] = 1;
  vector<int> ans;
  for (int i = 1, j = 1; i <= N; i = ++j) {
    while (re[j]) j++;
    for (int k = j; k >= i; k--) ans.push_back(k);
  }
  for (int i = 0; i < N; i++) cout << ans[i] << " \n"[i + 1 == N];
}

投稿日時:
最終更新: