Official

D - レコーダー/Recorder Editorial by Nyaan


この問題はレコーダーの動作を適切にシミュレーションすれば解くことができます。具体的には以下の手続きを実装すればよいです。

  • 十分長い bool 配列 \(\mathrm{recorded}\)\(i\) 番目の要素を「時刻 \(i\) から時刻 \(i+1\) までの間を録画したか?」を持つ変数とする。はじめ \(\mathrm{recorded}\) は false で初期化されている。
  • \(A_s, A_e\) を番組の開始時刻・終了時刻とする。はじめ \(A_s = A, A_e = R\) である。
  • \(i = 0, D, 2D, \dots\) の間以下の操作を行う。
    • まず \(B \lt i\) の場合、放映時刻が変更になっているので \(A_s \gets C, A_e \gets C + R\) に変更する。
    • また、\(A_e \leq i\) の場合はすでに番組が終了しているのでループを抜ける。
    • そうでない場合、\(\max(A_s, i)\) 以上 \(A_e\) 未満の区間に含まれる整数 \(j\) について、\(\mathrm{recorded}[j]\) を true にする。
  • ループを抜けた後、\(A_s\) 以上 \(A_e\) 未満の空間に含まれる \(j\) について \(\mathrm{recorded}[j]\) が true ならば答えは Yes 、そうでなければ No である。

計算量は \(\mathrm{O}(A+B+C+D+R)\) で十分高速です。

#include <iostream>
using namespace std;

int recorded[10000];
int main() {
  int A, B, C, D, R;
  cin >> A >> B >> C >> D >> R;
  int as = A;
  int ae = A + R;
  for (int i = 0;; i += D) {
    if (B < i) as = C, ae = C + R;
    if (ae <= i) break;
    for (int j = max(as, i); j < ae; j++) recorded[j] = 1;
  }
  int ans = 1;
  for (int i = as; i < ae; i++) {
    if (!recorded[i]) ans = 0;
  }
  cout << (ans ? "Yes" : "No") << endl;
}

posted:
last update: