summaryrefslogtreecommitdiff
path: root/datastructures
diff options
context:
space:
mode:
Diffstat (limited to 'datastructures')
-rw-r--r--datastructures/lichao.cpp57
1 files changed, 26 insertions, 31 deletions
diff --git a/datastructures/lichao.cpp b/datastructures/lichao.cpp
index 69ee47f..e12d243 100644
--- a/datastructures/lichao.cpp
+++ b/datastructures/lichao.cpp
@@ -1,49 +1,44 @@
vector<ll> xs; // IMPORTANT: Initialize before constructing Lichao!
+int findX(int i) {return distance(xs.begin(), lower_bound(all(xs), i));}
struct Fun{ // Default: Linear function. Change it to needed function type.
ll m, c;
- ll operator()(int x){
- return m*xs[x] + c;
- }
+ ll operator()(int x) {return m*xs[x] + c;}
};
// Default: Computes min. Change lines with comment for max.
struct Lichao{
- const Fun id = {0, inf}; // {0, -inf}
+ static constexpr Fun id = {0, inf}; // {0, -inf}
int n, cap;
vector<Fun> seg;
- Lichao(){
- n = sz(xs);
- for(cap = 1; cap < n; cap *= 2);
- seg.assign(2*cap, id);
- }
- void myInsert(Fun f, int l, int r, int i){
- while(i < 2*cap){
+ Lichao() : n(sz(xs)), cap(2<<__lg(n)), seg(2*cap, id) {}
+
+ void _insert(Fun f, int l, int r, int i) {
+ while (i < 2*cap){
int m = (l+r)/2;
- if(m >= n) {r = m; i = 2*i; continue;}
+ if (m >= n) {r = m; i = 2*i; continue;}
Fun &g = seg[i];
- if(f(m) < g(m)) swap(f, g); // >
- if(f(l) < g(l)) r = m, i = 2*i; // >
+ if (f(m) < g(m)) swap(f, g); // >
+ if (f(l) < g(l)) r = m, i = 2*i; // >
else l = m, i = 2*i+1;
- }
- }
- void mySegmentInsert(Fun f, int l, int r, int a, int b, int i){
- if(l <= a && b <= r) myInsert(f, a, b, i);
- else if(a < r && l < b){
+ }}
+ void insert(Fun f) {_insert(f, 0, cap, 1);}
+
+ void _segmentInsert(Fun f, int l, int r, int a, int b, int i) {
+ if (l <= a && b <= r) _insert(f, a, b, i);
+ else if (a < r && l < b){
int m = (a+b)/2;
- mySegmentInsert(f, l, r, a, m, 2*i);
- mySegmentInsert(f, l, r, m, b, 2*i+1);
- }
- }
- void insert(Fun f){myInsert(f, 0, cap, 1);}
- void segmentInsert(Fun f, ll l, ll r){
- mySegmentInsert(f, lower_bound(all(xs), l)-xs.begin(), lower_bound(all(xs), r)-xs.begin(), 0, cap, 1);
+ _segmentInsert(f, l, r, a, m, 2*i);
+ _segmentInsert(f, l, r, m, b, 2*i+1);
+ }}
+ void segmentInsert(Fun f, ll l, ll r) {
+ _segmentInsert(f, findX(l), findX(r), 0, cap, 1);
}
- ll myQuery(int x){
- int i = x+cap;
- ll ans = seg[i](x);
- while(i > 1) ans = min(ans, seg[i/=2](x)); // max
+
+ ll _query(int x) {
+ ll ans = inf; // -inf
+ for (int i = x + cap; i > 0; i /= 2) ans = min(ans, seg[i](x)); // max
return ans;
}
- ll query(ll x){return myQuery(lower_bound(all(xs),x)-xs.begin());}
+ ll query(ll x) {return _query(findX(x));}
};