Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
segtree.hpp
[詳解]
1#pragma once
2#include"../../kyopro_library/template.hpp"
3
4/// @brief セグメント木
5template<typename Monoid>
6struct SegTree {
7 using Type=typename Monoid::Type;
8 SegTree()=default;
9
10 /// @brief 要素数 n のセグ木を構築する
11 SegTree(int n) {
12 this->n=n;
13 dat.assign(n<<1,Monoid::id());
14 cand.reserve(100),cand_l.reserve(100),cand_r.reserve(100);
15 }
16
17 /// @brief 配列 v からセグ木を構築する
18 /// @note O(N)
19 SegTree(const vector<Type>& v) {
20 this->n=v.size();
21 dat.assign(n<<1,Monoid::id());
22 for(int i=0; i<n; i++) dat[i+n]=v[i];
23 for(int i=n-1; i>0; i--) dat[i]=Monoid::op(dat[i<<1],dat[i<<1|1]);
24 cand.reserve(100),cand_l.reserve(100),cand_r.reserve(100);
25 }
26
27 /// @brief i 番目の要素を x に変更する
28 /// @note O(log(N))
29 void set(int i, Type x) {
30 i+=n;
31 dat[i]=x;
32 while(i>>=1) dat[i]=Monoid::op(dat[i<<1],dat[i<<1|1]);
33 }
34
35 /// @brief 区間 [l, r) のモノイド積を返す
36 /// @note O(log(N))
37 Type fold(int l, int r) {
38 Type retl=Monoid::id(),retr=Monoid::id();
39 l+=n,r+=n;
40 while(l<r) {
41 if(l&1) retl=Monoid::op(retl,dat[l++]);
42 if(r&1) retr=Monoid::op(dat[--r],retr);
43 l>>=1,r>>=1;
44 }
45 return Monoid::op(retl,retr);
46 }
47
48 /// @brief 区間 [l, x) のモノイド積が f を満たすような最大の x >= l を返す
49 /// @attention `f(Monoid::id())=true` が成り立つ必要がある
50 /// @note O(log(N))
51 template<typename F>
52 int find_right(int l, F f) {
53 assert(f(Monoid::id()));
54 if(l==n) return n;
55 l+=n;
56 int r=n+n;
57 cand_l.clear(),cand_r.clear();
58 while(l<r) {
59 if(l&1) cand_l.push_back(l++);
60 if(r&1) cand_r.push_back(--r);
61 l>>=1,r>>=1;
62 }
63 cand=cand_l;
64 reverse(cand_r.begin(),cand_r.end());
65 cand.insert(cand.end(),cand_r.begin(),cand_r.end());
66 Type val=Monoid::id();
67 for(int i:cand) {
68 if(f(Monoid::op(val,dat[i]))) {
69 val=Monoid::op(val,dat[i]);
70 } else {
71 while(i<n) {
72 i<<=1;
73 if(f(Monoid::op(val,dat[i]))) {
74 val=Monoid::op(val,dat[i]);
75 i|=1;
76 }
77 }
78 return i-n;
79 }
80 }
81 return n;
82 }
83
84 /// @brief 区間 [x, r) のモノイド積が f を満たすような最小の x <= r を返す
85 /// @attention `f(Monoid::id())=true` が成り立つ必要がある
86 /// @note O(log(N))
87 template<typename F>
88 int find_left(int r,F f) {
89 assert(f(Monoid::id()));
90 if(r==0) return 0;
91 r+=n;
92 int l=n;
93 cand_l.clear(),cand_r.clear();
94 while(l<r) {
95 if(l&1) cand_l.push_back(l++);
96 if(r&1) cand_r.push_back(--r);
97 l>>=1,r>>=1;
98 }
99 cand=cand_r;
100 reverse(cand_l.begin(),cand_l.end());
101 cand.insert(cand.end(),cand_l.begin(),cand_l.end());
102 Type val=Monoid::id();
103 for(int i:cand) {
104 if(f(Monoid::op(dat[i],val))) {
105 val=Monoid::op(dat[i],val);
106 } else {
107 while(i<n) {
108 i=(i<<1)|1;
109 if(f(Monoid::op(dat[i],val))) {
110 val=Monoid::op(dat[i],val);
111 i^=1;
112 }
113 }
114 return i-n+1;
115 }
116 }
117 return 0;
118 }
119
120 /// @brief i 番目の要素を返す
121 /// @note O(1)
122 Type operator[](int i) { return dat[i+n]; }
123
124 /// @brief 配列のサイズを返す
125 int size() { return n; }
126
127private:
128 int n;
129 vector<Type> dat;
130 vector<int> cand,cand_l,cand_r;
131};
132
133#include"../../kyopro_library/others/monoid.hpp"
134
135/// @brief 区間クエリ
136namespace RangeQuery {
137 /// @brief 1点変更 / 区間 min
138 template<typename T, T max_value=INF>
139 struct Min { using Type=struct SegTree<Monoid::Min<T,max_value>>; };
140
141 /// @brief 1点変更 / 区間 max
142 template<typename T, T min_value=-INF>
143 struct Max { using Type=struct SegTree<Monoid::Max<T,min_value>>; };
144
145 /// @brief 1点変更 / 区間和
146 template<typename T>
147 struct Sum { using Type=struct SegTree<Monoid::Sum<T>>; };
148}
モノイド
Definition monoid.hpp:5
区間クエリ
Definition segtree.hpp:136
1点変更 / 区間 max
Definition segtree.hpp:143
1点変更 / 区間 min
Definition segtree.hpp:139
1点変更 / 区間和
Definition segtree.hpp:147
セグメント木
Definition segtree.hpp:6
int find_left(int r, F f)
区間 [x, r) のモノイド積が f を満たすような最小の x <= r を返す
Definition segtree.hpp:88
SegTree(const vector< Type > &v)
配列 v からセグ木を構築する
Definition segtree.hpp:19
int size()
配列のサイズを返す
Definition segtree.hpp:125
SegTree()=default
Type fold(int l, int r)
区間 [l, r) のモノイド積を返す
Definition segtree.hpp:37
Type operator[](int i)
i 番目の要素を返す
Definition segtree.hpp:122
void set(int i, Type x)
i 番目の要素を x に変更する
Definition segtree.hpp:29
SegTree(int n)
要素数 n のセグ木を構築する
Definition segtree.hpp:11
int find_right(int l, F f)
区間 [l, x) のモノイド積が f を満たすような最大の x >= l を返す
Definition segtree.hpp:52
const int INF
Definition template.hpp:13