解説
値xが区間[L,R]に何個含まれるかを高速に数える方法を考えます。
AmaxをmaxAiとします。
Fenwick TreeをAmax個持てばO(logAmax)で数えることができますが、サイズが103×5×105と巨大になりMLEします。
そこで、平方分割を用います。配列を長さNのバケットの分割します。各バケット内で各数値が何回出現するかをFenwick Treeで管理します。
クエリ処理
区間[L,R]が与えられた時、その範囲に含まれるバケットが完全に含まれる場合と一部だけ含まれる場合でそれぞれ数えます。
- 完全に含まれるバケット:Fenwick Treeで各数値を数えます
- 一部だけ含まれるバケット:個々の要素を数えます
値の更新は、数列の更新とその要素が属するバケットの個数を更新すれば良いです。
計算量
最頻値は一部だけ含まれるバケットの数え上げるのにO(N)、完全に含まれるバケットの数え上げるのにO(AmaxlogN)となり、合計でO(N+AmaxlogN)となります。
更新操作はFenwick Treeを使っているので O(logN) 時間で行えます。
実装