ABC
D
二分探索
ABC205 D - Kth Excluded
https://atcoder.jp/contests/abc205/tasks/abc205_d (opens in a new tab)
茶色上位。二分探索。
正の整数列 A について、各々の要素以下の数で、かつそれ以前の整数列に出現しない整数の個数をカウントしておく。
a = list(map(int,input().split()))
a_lower = [e-i for i,e in enumerate(a,1)]
a_lower
は単調増加する。
例えば入力が1 3 5 8 9 10 12 15 17 30
だとすると、a_lower
は0 1 2 4 4 4 5 7 8 20
となる。
以下はこの例をもとに考える。
K = 3
のときを考える。
a_lower
上で3
が2
と4
の間に位置することから、それに対応するa
での5
と8
の間に解は存在する。a_lower
の2
に対応する、a
での5
から3-2=1
分進んだ6
が解となる。
K = 4
のときを考える。
a_lower
上で4
が2
と4
の間に位置することから、それに対応するa
での5
と8
にの間に解は存在する。a_lower
の2
に対応する、a
での5
から4-2=2
分進んだ7
が解となる。
K = 7
のときを考える。
a_lower
上で7
が5
と7
の間に位置することから、それに対応するa
での12
と15
にの間に解は存在する。a_lower
の5
に対応する、a
での12
から7-5=2
分進んだ14
が解となる。
以上よりターゲット値で二分探索(左)を行い、得られた値をi
とすると、インデックスi-1
に対応するa
の値から、ターゲット値からインデックスi-1
に対応するa_lower
に値を引いたものを加えればよいこととなる。
from bisect import bisect_left
k = <target>
i = bisect_left(a_lower,k)
print(a[i-1] + (k - a_lower[i-1]))
尚、インデックスを-1 することから、ターゲットがa_lower[0]
以下の値であった場合、即ち二分探索して、0 が返ってくるような場合はは別途処理が必要である。
from bisect import bisect_left
n,q = map(int,input().split())
a = list(map(int,input().split()))
a_lower = [e-i-1 for i,e in enumerate(a)]
for _ in range(q):
k = int(input())
if k <= a_lower[0]:
print(k)
else:
i = bisect_left(a_lower,k)
print(a[i-1] + (k-a_lower[i-1]))