区間の半数を超える同一要素(dominator)があるかどうか判定するクエリ問題。一点更新もある。
方針 1
Editorialの方針。
2つの区間を合併するとき、ある要素が合併後の区間で半数を超えるためには、2つの区間のうちの少なくともいっぽうで半数を超えていなくてはならない、ということを利用できる。
セグメント木の各ノードに、区間内の各要素の出現頻度を保持するマップと(存在すれば)区間のdominatorを保持しておく。質問クエリに対しては、質問の区間がセグ木上の個の区間に分割できるので、個のdominatorの候補を、個のマップに関して調べる。だが、ハッシュテーブルを使うなのでかなり重い。
https://www.codechef.com/viewsolution/42694801 1.63 sec.
方針2
を決めておいて、質問クエリの度に区間から回無作為に要素を抽出して回以上出現した要素についてrange frequency queryを適用してdominatorかどうか調べる。
正答率を評価するには二項分布のCDFを調べればよい。たとえば100回抽出して17回以上出現した要素について調べることにすると、確率1/2で成功する試行を100回繰り返して成功回数が16回以下になる確率が以下で、個の質問に対して少なくとも1回間違える確率は以下と求まる。
https://www.codechef.com/viewsolution/43903194 0.68 sec.
方針 3
区間内でトーナメントのようなことをする。セグメント木の各ノードにを保持することにして、葉から
という演算でマージしていくと(結合法則は成り立たないが)マージの順番や区間の大きさによらず、dominatorは必ず残る。実際に残った要素がその区間でdominatorかどうか判定するためにはrange frequency queryに答えらればよい。。
https://www.codechef.com/viewsolution/42748384 0.22 sec.
方針4
区間の長さの閾値を適当に決めて、長さ未満の区間は愚直に判定する。
長さ以上の区間については、その区間のdominatorは与えられた列中に個より多く含まれることを利用できる。具体的には、列中に個より多く存在する数については個別にBIT等を作っておいて、range frequency queryに答えられるようにする。このような数は高々種類しかないので、質問に対しては個のBITをすべて調べれば答えられることになる。
前処理: 質問クエリ(長さ未満): 質問クエリ(長さ以上): 更新クエリ:
とすると。