This documentation is automatically generated by online-judge-tools/verification-helper
 Line Container
 Line Container
    #include "library/dynamic-programming/line-container.hpp"This is currently modified for minimums. To modify for maximums, comment the first line in add_line and get rid of the negative of the return statement in query.
This implementation is also blazingly fast for some reason, performs almost like constant time per operation.
add_line(k, m): Adds a line with slope $k$ and $y$-intercept $m$.query(x): Finds minimum of lines at location $x$.#pragma once
template <class T> struct Line {
	mutable T k, m, p;
	
	bool operator<(const Line<T>& o) const { return k < o.k; }
	bool operator<(T x) const { return p < x; }
};
template <class T> struct LineContainer : std::multiset<Line<T>, std::less<>> {
	// (for doubles, use INF = 1/.0, div(a,b) = a/b)
	const T INF = std::numeric_limits<T>::max();
	T div(T a, T b) { // floored division
		return a / b - ((a ^ b) < 0 && a % b); 
	}
	using super = std::multiset<Line<T>, std::less<>>;
	using iterator = typename LineContainer<T>::iterator;
	
	bool isect(iterator x, iterator y) {
		if (y == super::end()) 
			return x->p = INF, 0;
		if (x->k == y->k) 
			x->p = x->m > y->m ? INF : -INF;
		else 
			x->p = div(y->m - x->m, x->k - y->k);
		return x->p >= y->p;
	}
	
	void add_line(T k, T m) {
		k = -k, m = -m;
		auto z = super::insert({k, m, 0}), y = z++, x = y;
		while (isect(y, z)) 
			z = super::erase(z);
		if (x != super::begin() && isect(--x, y)) 
			isect(x, y = super::erase(y));
		while ((y = x) != super::begin() && (--x)->p >= y->p)
			isect(x, super::erase(y));
	}
	
	T query(T x) {
		assert(!super::empty());
		auto l = *super::lower_bound(x);
		return -(l.k * x + l.m);
	}
};template <class T> struct Line {
	mutable T k, m, p;
	
	bool operator<(const Line<T>& o) const { return k < o.k; }
	bool operator<(T x) const { return p < x; }
};
template <class T> struct LineContainer : std::multiset<Line<T>, std::less<>> {
	// (for doubles, use INF = 1/.0, div(a,b) = a/b)
	const T INF = std::numeric_limits<T>::max();
	T div(T a, T b) { // floored division
		return a / b - ((a ^ b) < 0 && a % b); 
	}
	using super = std::multiset<Line<T>, std::less<>>;
	using iterator = typename LineContainer<T>::iterator;
	
	bool isect(iterator x, iterator y) {
		if (y == super::end()) 
			return x->p = INF, 0;
		if (x->k == y->k) 
			x->p = x->m > y->m ? INF : -INF;
		else 
			x->p = div(y->m - x->m, x->k - y->k);
		return x->p >= y->p;
	}
	
	void add_line(T k, T m) {
		k = -k, m = -m;
		auto z = super::insert({k, m, 0}), y = z++, x = y;
		while (isect(y, z)) 
			z = super::erase(z);
		if (x != super::begin() && isect(--x, y)) 
			isect(x, y = super::erase(y));
		while ((y = x) != super::begin() && (--x)->p >= y->p)
			isect(x, super::erase(y));
	}
	
	T query(T x) {
		assert(!super::empty());
		auto l = *super::lower_bound(x);
		return -(l.k * x + l.m);
	}
};