需要购买\(n\)块土地,每块土地有一个长\(r_i\)与宽\(c_i\)。可以将这些土地打成几包购买。每包土地的价格为这包土地中最大的长乘以最大的宽。求最小花费。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 50005;
struct Earth {
    long long r, c;
    bool operator < (const Earth &res) const {return c < res.c;}
} ar[MAXN], a[MAXN]; //结构体,ar为踢去没用的土地后的数组。 
int n, N;
long long f[MAXN];
int head, tail, que[MAXN * 5];
inline double g(int j, int k) {
    return (f[j] - f[k]) / (ar[k + 1].r - ar[j + 1].r);
} //将不等式的右边写成函数。 
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%lld%lld", &a[i].r, &a[i].c);
    sort(a + 1, a + n + 1);
    for (int i = 1; i <= n; i++) {
        while (N && ar[N].r <= a[i].r)
            N--; //如果宽比前面的大(排序决定),长也比前面大,就将前面的踢出(单调栈)。 
        ar[++N] = a[i];
    }
    head = tail = 0;
    que[0] = 0, /*队列里存放的是数组下标*/f[0] = 0;
    for (int i = 1; i <= N; i++) {
        while (head < tail && ar[i].c >= g(que[head], que[head + 1]))
            head++; //维护时间 
        f[i] = f[que[head]] + ar[que[head] + 1].r * ar[i].c; //更新答案 
        while (head < tail && g(que[tail - 1], que[tail]) >= g(que[tail], i))
            tail--; //维护单调性 
        que[++tail] = i; //加入元素 
    }
    printf("%lld\n", f[N]);
    return 0;
}原文:https://www.cnblogs.com/JackHomes/p/9467006.html