Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
sqrt_tree.hpp
[詳解]
1#include"../../kyopro_library/template.hpp"
2
3/// @brief 更新 O(1) クエリ O(sqrt(N)) の改造版セグ木
4/// @brief Mo's Algorithmとの相性が良い
5/// @note モノイドではなくアーベル群が乗る(モノイドや群の場合、更新が Θ(√N) でメリットがない)
6/// @ref https://atcoder.jp/contests/abc405/submissions/65704867
7template<typename Abel>
8struct SqrtTree {
9 using Type=typename Abel::Type;
10 SqrtTree()=default;
11
12 SqrtTree(int n) {
13 this->n=n;
14 rn=1;
15 while(rn*rn<n) rn++;
16 dat.assign(rn,Abel::id());
17 dat2.assign(n,Abel::id());
18 dat2_inv.assign(n,Abel::id());
19 }
20
21 /// @brief 配列 v で初期化する
22 SqrtTree(const vector<Type>& v) {
23 this->n=v.size();
24 rn=1;
25 while(rn*rn<n) rn++;
26 dat.assign(rn,Abel::id());
27 dat2=v;
28 for(int i=0; i<rn; i++) {
29 for(int j=i*rn; j<min((i+1)*rn,n); j++) {
30 dat[i]=Abel::op(dat[i],dat2[j]);
31 dat2_inv[j]=Abel::inv(dat2[j]);
32 }
33 }
34 }
35
36 /// @brief 配列 v とその逆元 v_inv で初期化する
37 SqrtTree(const vector<Type>& v, const vector<Type>& v_inv) {
38 this->n=v.size();
39 rn=1;
40 while(rn*rn<n) rn++;
41 dat.assign(rn,Abel::id());
42 dat2=v;
43 dat2_inv=v_inv;
44 for(int i=0; i<rn; i++) {
45 for(int j=i*rn; j<min((i+1)*rn,n); j++) {
46 dat[i]=Abel::op(dat[i],dat2[j]);
47 }
48 }
49 }
50
51 /// @brief i 番目の要素を x に更新する
52 /// @note O(f) (f : 逆元を求めるのにかかる計算量)
53 void set(int i, Type x) {
54 int j=i/rn;
55 dat[j]=Abel::op(dat[j],Abel::inv(dat2[i]));
56 dat2[i]=x;
57 dat[j]=Abel::op(dat[j],dat2[i]);
58 dat2_inv[i]=Abel::inv(dat2[i]);
59 }
60
61 /// @brief i 番目の要素を x に更新し、その逆元を x_inv に更新する
62 void set(int i, Type x, Type x_inv) {
63 int j=i/rn;
64 dat[j]=Abel::op(dat[j],dat2_inv[i]);
65 dat2[i]=x;
66 dat2_inv[i]=x_inv;
67 dat[j]=Abel::op(dat[j],dat2[i]);
68 }
69
70 /// @brief 区間 [l, r) の群積を返す
71 /// @note O(√N)
72 Type fold(int l, int r) {
73 Type ret=Abel::id();
74 while(l<r) {
75 if(l%rn==0 && l+rn<=r) {
76 ret=Abel::op(ret,dat[l/rn]);
77 l+=rn;
78 } else {
79 ret=Abel::op(ret,dat2[l]);
80 l++;
81 }
82 }
83 return ret;
84 }
85
86 Type operator[](int i) const { return dat2[i]; }
87 int size() const { return n; }
88
89private:
90 int n,rn;
91 vector<Type> dat,dat2,dat2_inv;
92};
更新 O(1) クエリ O(sqrt(N)) の改造版セグ木
Definition sqrt_tree.hpp:8
Type fold(int l, int r)
区間 [l, r) の群積を返す
Definition sqrt_tree.hpp:72
SqrtTree(const vector< Type > &v, const vector< Type > &v_inv)
配列 v とその逆元 v_inv で初期化する
Definition sqrt_tree.hpp:37
void set(int i, Type x)
i 番目の要素を x に更新する
Definition sqrt_tree.hpp:53
Type operator[](int i) const
Definition sqrt_tree.hpp:86
void set(int i, Type x, Type x_inv)
i 番目の要素を x に更新し、その逆元を x_inv に更新する
Definition sqrt_tree.hpp:62
SqrtTree(const vector< Type > &v)
配列 v で初期化する
Definition sqrt_tree.hpp:22
int size() const
Definition sqrt_tree.hpp:87
SqrtTree()=default
SqrtTree(int n)
Definition sqrt_tree.hpp:12