
use proconio::input;
fn main() {
input! {
n: usize,
mut a: [u64; n],
q: usize,
b: [u64; q],
}
a.sort_unstable();
a.dedup();
for b in b {
let complain = match a.binary_search(&b) {
Ok(_) => 0,
Err(0) => a[0] - b,
Err(x) if x == a.len() => b - a[x - 1],
Err(x) => (a[x] - b).min(b - a[x - 1]),
};
println!("{}", complain);
}
}Vec 型に binary_search() メソッドが実装されています。binary_search() の使用例は以下のプログラムの通りです。
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
assert_eq!(s.binary_search(&13), Ok(9));
assert_eq!(s.binary_search(&4), Err(7));
assert_eq!(s.binary_search(&100), Err(13));
let r = s.binary_search(&1);
assert!(match r { Ok(1..=4) => true, _ => false, });Ok(i) として、同じ値が見つからなかった場合は Err(i) として、要素が挿入される場所を返します。また、Vec のどの値よりも大きかった場合は添字の範囲外となる Vec::len() がが返ってくることに注意してください。さらに、同じ値が複数ある場合はそのうちのどれかの添字が返ります。これを踏まえて、以下のように binary_search() の戻り値に対して match 式で場合分けを行いました。
let complain = match a.binary_search(&b) {
Ok(_) => 0,
Err(0) => a[0] - b,
Err(x) if x == a.len() => b - a[x - 1],
Err(x) => (a[x] - b).min(b - a[x - 1]),
};Ok(_) => 0
Ok が返ってくる時は b と全く同じレートの教室があるということを意味しているため、その差は常に 0 となります。Err(0) => a[0] - b
Err(0) の時、b は a[0] より確実に小さい値となります。Err(x) if x == a.len() => b - a[x - 1]
Err(x) if x == a.len() となるのは b が a のどの値よりも大きい場合です。Err(x)
上のどのパターンでもない場合にマッチします。match 式で場合分けを行うのが面倒な気もしますが、結果をそのまま変数に代入できるのはいいと思います。