[Usaco2008 Mar]土地购买 BZOJ 1597

Description

农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <
= 1,000,000; 1 <= 长 <= 1,000,000). 每块土地的价格是它的面积,但FJ可以同时购买多快土地. 这些土地的价
格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果FJ买一块3x5的地和一块5x3的地,则他需要
付5x5=25. FJ希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费.

Input

第1行: 一个数: N
第2..N+1行: 第i+1行包含两个数,分别为第i块土地的长和宽

Output

第一行: 最小的可行费用.

思路

f [ i ] = m i n ( f [ j ] + y [ j + 1 ] x [ i ] ) ( 0 j < i ) (必须将被包含的矩阵清除)
斜率优化一波

代码

#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
typedef double DB;
typedef long long LL;
const int maxn=5e4+5;
LL f[maxn];
int N,j,tot,hed,til,que[maxn];
struct matrix{LL x,y;}M[maxn];
inline bool operator <(matrix x,matrix y) {return x.x<y.x||x.x==y.x&&x.y<y.y;}
inline int read() {
    int ret=0,f=1;char ch=getchar();
    for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
    for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
    return ret*f;
}
inline DB X(int i) {return M[i+1].y;}
inline DB Y(int i) {return f[i];}
inline DB Slope(int i,int j) {return (Y(i)-Y(j))/(X(i)-X(j));}
int main() {
    N=read();
    for (int i=1; i<=N; i++) M[i].x=read(),M[i].y=read();
    sort(M+1,M+1+N);
    for (int i=1; i<=N; i++) {while (tot&&M[tot].y<=M[i].y) tot--;M[++tot]=M[i];}
    N=tot,hed=til=1;
    for (int i=1; i<=N; i++) {
        while (hed<til&&Slope(que[hed],que[hed+1])>=-M[i].x) hed++;
        j=que[hed],f[i]=f[j]+M[i].x*M[j+1].y;
        while (hed<til&&Slope(que[til],que[til-1])<Slope(que[til],i)) til--;
        que[++til]=i;
    }
    printf("%lld\n",f[N]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zj_js_zxb/article/details/80456976
今日推荐