# include <iomanip>
# include <iostream>
namespace
{
void rule()
{
std::cout << "------------------------------------------------------------\n";
}
void show_divide_and_conquer_dp()
{
std::cout << "[1] Divide & Conquer DP optimization\n";
rule();
const size_t n = demand.
size();
const size_t groups = 3;
pref(0) = 0;
for (size_t i = 0; i < n; ++i)
pref(i + 1) = pref[i] + demand[i];
const auto cost = [&] (
const size_t k,
const size_t i) ->
long long
{
const long long seg = pref[i] - pref[
k];
return seg * seg;
};
const auto res = divide_and_conquer_partition_dp<long long>(
groups, n, cost
);
std::cout << "Demand sequence: ";
for (size_t i = 0; i < n; ++i)
std::cout << demand[i] << (i + 1 == n ? '\n' : ' ');
std::cout << "Groups: " << groups << "\n";
std::cout << "Optimal cost: " << res.optimal_cost << "\n";
size_t i = n;
for (size_t g = groups; g-- > 1; )
{
const size_t k = res.split[g + 1][i];
}
std::cout << "Split points (prefix indices): ";
for (
size_t p = bounds.
size(); p-- > 0; )
{
std::cout << bounds[p];
if (p > 0)
std::cout << " -> ";
}
std::cout << "\n";
rule();
std::cout << "\n";
}
void show_knuth_optimization()
{
std::cout << "[2] Knuth optimization (optimal adjacent merge)\n";
rule();
const auto res = optimal_merge_knuth(blocks);
std::cout << "Blocks: ";
for (
size_t i = 0; i < blocks.
size(); ++i)
std::cout << blocks[i] << (i + 1 == blocks.
size() ?
'\n' :
' ');
std::cout << "Minimum merge cost: " << res.optimal_cost << "\n";
std::cout << "Top split (k for [0,n)): "
<< res.opt[0][blocks.
size()] <<
"\n";
rule();
std::cout << "\n";
}
void show_cht_and_li_chao_geometry()
{
std::cout << "[3] CHT + Li Chao (geometry-friendly lower envelopes)\n";
rule();
std::cout << "Monotone-slope CHT for min y = m*x + b:\n";
for (long long x = -4; x <= 8; x += 3)
std::cout << " x=" << std::setw(3) << x
<<
" min=" << std::setw(5) << cht.
query(x) <<
"\n";
std::cout << "\nGeometric application: weighted squared distance\n";
std::cout << " min_j ((x_i - x_j)^2 + w_j) via Li Chao\n\n";
const auto best = min_weighted_squared_distance_1d(xs, ws);
std::cout << " "
<< std::left << std::setw(8) << "x_i"
<< std::setw(8) << "w_i"
<< std::setw(12) << "min value"
<< "\n";
for (
size_t i = 0; i < xs.
size(); ++i)
{
std::cout << " "
<< std::left << std::setw(8) << xs[i]
<< std::setw(8) << ws[i]
<< std::setw(12) << best[i]
<< "\n";
}
rule();
std::cout << "\n";
}
void show_monotone_queue_dp()
{
std::cout << "[4] Monotone queue optimization (windowed transitions)\n";
rule();
const size_t window = 3;
const auto res = monotone_queue_min_dp<long long>(base, window);
std::cout << "Base cost: ";
for (
size_t i = 0; i < base.
size(); ++i)
std::cout << base[i] << (i + 1 == base.
size() ?
'\n' :
' ');
std::cout << "Window: " << window << "\n";
std::cout <<
"Final minimum cost: " << res.dp[base.
size() - 1] <<
"\n";
size_t i = base.
size() - 1;
while (i > 0)
{
i = res.parent[i];
}
std::cout << "Chosen chain: ";
for (
size_t p = path.
size(); p-- > 0; )
{
std::cout << path[p];
if (p > 0)
std::cout << " -> ";
}
std::cout << "\n";
rule();
std::cout << "\n";
}
}
{
std::cout << "\n=== DP Optimizations: D&C, Knuth, CHT/Li Chao, Monotone Queue ===\n\n";
show_divide_and_conquer_dp();
show_knuth_optimization();
show_cht_and_li_chao_geometry();
show_monotone_queue_dp();
std::cout << "Done.\n";
return 0;
}
Classical DP optimization toolkit: D&C DP, Knuth, CHT, Li Chao, and monotone-queue transitions.
Simple dynamic array with automatic resizing and functional operations.
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
T & append(const T &data)
Append a copy of data
Convex Hull Trick for minimum queries.
T query(const T x) const
Query minimum value at arbitrary x (O(log n)).
void add_line(const T slope, const T intercept)
Insert a new line; slopes must be non-increasing.
Main namespace for Aleph-w library functions.