公式
B - 最寄りの郵便局 / Nearest Post Office 解説 by admin
GPT 5.2 High概要
郵便局の座標をソートし、各人の住居位置 \(P, Q\) に対して「最寄りの郵便局」を二分探索で求め、登録後の利用者数(+1ずつ)を合計します。
考察
- 各人は「距離が最小」の郵便局を選び、同距離なら「座標が小さい方」を選びます。
- 素朴に、各人について全ての郵便局との距離を調べると \(O(N)\) で最寄りが求まりますが、今回 \(N \le 2 \times 10^5\) なので(2人分とはいえ)十分間に合います。
ただし、競技プログラミングとしては「最寄り問題はソート+二分探索で一般に高速化できる」という典型を押さえるのが重要です(人が増える設定でも拡張しやすい)。 - 1次元(一直線)上では、座標をソートしておけば、ある位置
posの最寄り候補はpos以上で最初に現れる郵便局(右側候補)- その1つ左の郵便局(左側候補) の高々2つに絞れます。なぜなら、ソート済み配列ではそれより遠い点は必ず距離が大きくなるためです。
- 同距離のときは座標が小さい郵便局を選ぶ必要があります。
これは「左候補と右候補の距離が等しいなら左を採用」とすれば、そのままタイブレーク条件(座標が小さい方)を満たします。 - 最後の合計は少し注意が必要で、二人が別の郵便局なら
- \((C_{ip}+1) + (C_{iq}+1) = C_{ip} + C_{iq} + 2\) 二人が同じ郵便局なら
- \(C_{i}+2\) を1回だけ数えます。
アルゴリズム
- 郵便局データ \((X_i, C_i)\) を \(X_i\) で昇順ソートする。
- ソート後の座標配列
xsを作る。 bisect_left(xs, pos)でposを挿入できる位置iを求める。i = 0なら最寄りは先頭i = Nなら最寄りは末尾- それ以外なら左候補
i-1と右候補iの距離を比較し、
\(|pos-xs[i-1]| \le |xs[i]-pos|\) なら左、そうでなければ右を選ぶ
(\(\le\) により同距離なら左=座標が小さい方を選べる)
- 上を \(P, Q\) それぞれに対して行い、最寄り郵便局のインデックス
ip, iqを得る。 ip == iqなら答えはcs[ip] + 2、違うならcs[ip] + cs[iq] + 2を出力する。
(例)xs = [0, 10], pos = 5 のとき
左距離 \(|5-0|=5\)、右距離 \(|10-5|=5\) で同距離なので左(座標0)を選びます。
計算量
- 時間計算量: ソートが \(O(N \log N)\)、二分探索は2回で \(O(\log N)\) なので合計 \(O(N \log N)\)
- 空間計算量: 配列保持に \(O(N)\)
実装のポイント
bisect_leftの戻り値iは「xs[i] >= posとなる最小の i」です。端(i=0やi=N)の処理を忘れないようにします。タイブレーク(同距離なら座標が小さい方)を満たすには、距離比較を
dl <= drとして左を優先します。最終出力は「登録後」なので、二人分で必ず
+2が入ります。ただし同じ郵便局ならその郵便局の人数を1回だけ数える(C + 2)点に注意します。ソースコード
import sys
import bisect
def nearest_index(xs, pos):
i = bisect.bisect_left(xs, pos)
if i == 0:
return 0
if i == len(xs):
return len(xs) - 1
left = i - 1
right = i
dl = abs(pos - xs[left])
dr = abs(xs[right] - pos)
if dl <= dr:
return left
else:
return right
def main():
input = sys.stdin.readline
N, P, Q = map(int, input().split())
offices = [tuple(map(int, input().split())) for _ in range(N)]
offices.sort()
xs = [x for x, _ in offices]
cs = [c for _, c in offices]
ip = nearest_index(xs, P)
iq = nearest_index(xs, Q)
if ip == iq:
ans = cs[ip] + 2
else:
ans = cs[ip] + cs[iq] + 2
print(ans)
if __name__ == "__main__":
main()
この解説は gpt-5.2-high によって生成されました。
投稿日時:
最終更新: