Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
mo.hpp
[詳解]
1#include"../../kyopro_library/template.hpp"
2
3/// @brief Mo's Algorithm
4/// @ref https://ei1333.hateblo.jp/entry/2017/09/11/211011
5struct Mo {
6 /// @brief コンストラクタ
7 Mo(int n) {
8 this->n=n;
9 q=0;
10 }
11
12 /// @brief クエリ [l, r) を追加する
13 void add(int l, int r) {
14 q++;
15 ls.push_back(l);
16 rs.push_back(r);
17 }
18
19 /// @brief クエリを実行する
20 /// @param add_left `add_left(i)` i 番目の要素が左から加わるときの処理
21 /// @param add_right `add_right(i)` i 番目の要素が右から加わるときの処理
22 /// @param del_left `del_left(i)` i 番目の要素が左から抜けるときの処理
23 /// @param del_right `del_right(i)` i 番目の要素が右から抜けるときの処理
24 /// @param out `out(i)` i 番目のクエリの答えを求めたときの処理
25 /// @note O(N sqrt(Q))
26 template<typename F1, typename F2, typename F3, typename F4, typename F5>
27 void execute(F1&& add_left, F2&& add_right, F3&& del_left, F4&& del_right, F5&& out) {
28 vector<int> qi(q); iota(qi.begin(),qi.end(),0);
29
30 // https://nyaannyaan.github.io/library/misc/mo.hpp.html
31 const int wid=max<int>(1,1.0*n/max<double>(1.0,sqrt(q*2.0/3.0)));
32 sort(qi.begin(),qi.end(),[&](int a, int b) {
33 if(ls[a]/wid!=ls[b]/wid) return ls[a]<ls[b];
34 if((ls[a]/wid)&1) return rs[a]<rs[b];
35 return rs[a]>rs[b];
36 });
37
38 int nl=0,nr=0;
39 for(int& i: qi){
40 while(nl>ls[i]) add_left(--nl);
41 while(nr<rs[i]) add_right(nr++);
42 while(nl<ls[i]) del_left(nl++);
43 while(nr>rs[i]) del_right(--nr);
44 out(i);
45 }
46 }
47
48private:
49 int n,q;
50 vector<int> ls,rs;
51};
Mo's Algorithm https://ei1333.hateblo.jp/entry/2017/09/11/211011
Definition mo.hpp:5
Mo(int n)
コンストラクタ
Definition mo.hpp:7
void execute(F1 &&add_left, F2 &&add_right, F3 &&del_left, F4 &&del_right, F5 &&out)
クエリを実行する
Definition mo.hpp:27
void add(int l, int r)
クエリ [l, r) を追加する
Definition mo.hpp:13