Official

D - 塗り重ねられた壁 / Repainted Wall Editorial by kyopro_friends


この問題は俗に イベントソート と呼ばれる手法を用いて解くことができます。

問題は次のように読み替えることができます:
高橋君は、 \(N\) 人のユーザーがいる web サービスを運営しています。 \(i\) 番目のユーザは時刻 \(L_i\) ​にログインし、時刻 \(R_i\) ​にログアウトしました。 \(K\) 人以上がログインしていた時間の長さの合計を求めてください。

この問題はログインとログアウトの発生を時刻順に処理することで解くことができます。

実装例 (C++)

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

int main(){
  int n, k;
  cin >> n >> k;
  vector<pair<int,int>>events;
  for(int i=0; i<n; i++){
    int l, r;
    cin >> l >> r;
    events.push_back({l, 1});
    events.push_back({r, -1});
  }
  sort(events.begin(), events.end());

  int ans = 0;
  int prev_time = 0;
  int crr_count = 0;
  for(auto [crr_time, delta]: events){
    if(crr_count >= k){
      ans += crr_time - prev_time;
    }
    crr_count += delta;
    prev_time = crr_time;
  }

  cout << ans << endl;
}

実装例 (Python)

N, K = map(int, input().split())
events = []
for _ in range(N):
  L, R = map(int, input().split())
  events.append((L, 1))
  events.append((R, -1))

events.sort()

ans = 0
prev_time = 0
crr_count = 0
for crr_time, delta in events:
  if crr_count >= K:
    ans += crr_time - prev_time
  crr_count  += delta
  prev_time = crr_time

print(ans)

posted:
last update: