summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas Schwebler <lucas.schwebler@gmail.com>2023-09-12 15:38:42 +0200
committerLucas Schwebler <lucas.schwebler@gmail.com>2023-09-12 15:38:42 +0200
commitcc86ae3dcc48e187d626584b22f66ab6906a9564 (patch)
tree1a3db1071f7c8390a9a521db6c3edea2b77eb898
parent606b5c772b787ab205a37ae1a151f72d5f93f991 (diff)
add lichao
-rw-r--r--datastructures/lichao.cpp49
1 files changed, 49 insertions, 0 deletions
diff --git a/datastructures/lichao.cpp b/datastructures/lichao.cpp
new file mode 100644
index 0000000..69ee47f
--- /dev/null
+++ b/datastructures/lichao.cpp
@@ -0,0 +1,49 @@
+vector<ll> xs; // IMPORTANT: Initialize before constructing Lichao!
+
+struct Fun{ // Default: Linear function. Change it to needed function type.
+ ll m, 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}
+ 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){
+ int m = (l+r)/2;
+ 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; // >
+ 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){
+ 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);
+ }
+ ll myQuery(int x){
+ int i = x+cap;
+ ll ans = seg[i](x);
+ while(i > 1) ans = min(ans, seg[i/=2](x)); // max
+ return ans;
+ }
+ ll query(ll x){return myQuery(lower_bound(all(xs),x)-xs.begin());}
+};