Official

D - Wi-Fiスポットの接続 / Wi-Fi Spot Connection Editorial by kyopro_friends


区間 \([0,L]\) を時刻だと思うことで、問題は次のように読み替えることができます:

\(N\) 個の Wi-Fi ルーターがあります。\(i\) 個目のルータは時刻 \(X_i-R_i\) に ON になり、時刻 \(X_i+R_i\) に OFF になります。時刻 \(0\) から \(L\) まで常に少なくとも1つのルーターが ON ですか?」

番兵として、時刻 \(L\) に ON になるルーターを追加しておきます。このルーターは時刻 \([0,L]\) の範囲に影響を与えないため、答えに影響を与えません。

この問題は「次に全てのルーターが OFF になる時刻」を保持しながら、時刻順にルーターが ON になるイベントを確認し、保持した情報を次のように更新すればよいです。

  • 「次に全てのルーターが OFF になる時刻」を 0 で初期化する
  • ON になる時刻が早いルーターから順に以下を行う
    • ON になる時刻が「次に全てのルーターが OFF になる時刻」より後である場合、その間で全てのルーターが OFF になっているため答えは No
    • そうでない場合、そのルーターがOFFになる時刻を確かめ、「次に全てのルーターが OFF になる時刻」を更新する
  • 全てのルーターを処理できたら答えは Yes(制約より最後に処理されるのは番兵であり、番兵の存在により「次に全てのルーターが OFF になる時刻」が \(L\) 以降であることがわかるため)

実装例 (C++)

#include <bits/stdc++.h>
using namespace std;

int main() {
  int n, l;
  cin >> n >> l;

  vector<pair<int, int>> rooter;
  rooter.push_back({l, l});  // 番兵

  for(int i=0; i<n; i++){
    int x, r;
    cin >> x >> r;
    rooter.push_back({x-r, x+r});
  }

  sort(rooter.begin(), rooter.end());

  int end = 0;
  for (auto [on, off]: rooter) {
    if(on > end){
      cout << "No" << endl;
      return 0;
    }
    end = max(end, off);
  }

  cout << "Yes" << endl;
}

実装例 (Python)

N, L = map(int,input().split())
rooter = [(L, L)]  # 番兵
for _ in range(N):
  X, R = map(int,input().split())
  rooter.append((X-R, X+R))

rooter.sort()
end = 0
for on, off in rooter:
  if on > end:
    print("No")
    break
  end = max(end, off)
else:
  print("Yes")

posted:
last update: