I - Distance Component Size Query Editorial
by
Shirotsume
$K$ がクエリごとに変更される場合も解ける方法
もとの問題では \(K\) が固定されていましたが,クエリごとに \(K\) の値が変化するような場合でも解くことができるので,方法を紹介します.
集合 \(S\) および,\(S\) に現れる値を昇順に並べたときの隣接項の差分の列 \(T\) を管理することにします.
例えば,\(S = \{ 1, 3, 7 \}\) のとき \(T = [2, 4] \) となります.クエリ 1 に対する \(S\) の管理は平衡二分木(C++ならstd::set, Pythonなら SortedSet)を用いて行います.\(T\) の管理は,クエリをあらかじめ先読みしておいて現れる値を座標圧縮し,Segment Tree で行います(\(S\) に含まれない要素に対応する \(T\) の位置には,絶対値が十分大きい負の値を入れておきます).これらの方法により,クエリ 1 は\(O(\log Q)\) でできます.
クエリ 2 について考えます.ここで,\(S\) を昇順に並べて隣接しない要素同士に張られる辺は無視して良いことを利用します.\(S\) の小さいほうから \(i\) 個目の値と \(i + 1\) 個目の間に辺が張られることと, \(T_i\) が \(K\) 以下であることは同値なので,指定された \(x\) から右側と左側それぞれに対して \(T_j \leq K\) であるような値がいくつ連続しているかをそれぞれ数えればよいです.これは,Segment Tree 上で二分探索を行うことにより可能です. うまく二分探索を行えば,計算量はクエリごとに \(O( \log Q)\) です(AtCoder Libraryの実装では,max_right や min_leftを利用できます).
posted:
last update: