zoukankan      html  css  js  c++  java
  • BZOJ 1597: [Usaco2008 Mar]土地购买 斜率优化

    1597: [Usaco2008 Mar]土地购买

    Time Limit: 10 Sec  Memory Limit: 162 MB

    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

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

    Sample Input

    4
    100 1
    15 15
    20 5
    1 100

    输入解释:

    共有4块土地.

    Sample Output

    500

    HINT

    题解:

      按照X排序, 手动删掉一些无影响的选择

      剩下的都是 X增大,Y减小的矩阵

      那么答案必须是选择一段连续的矩阵了

      这个时候就可以DP

      他是有单调性的

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define LL long long
    const int N = 1e5+10, inf = 1e9, mod = 1e9+7;
    struct ss{
        LL x,y;
    }Q[N],tmp[N];
    int cmp1(ss s1,ss s2) {
        if(s1.x == s2.x) return s1.y < s2.y;
        else return s1.x < s2.x;
    }
    int cmp2(ss s1,ss s2) {
        if(s1.y == s2.y) return s1.x < s2.x;
        else return s1.y < s2.y;
    }
    int n,q[N];
    LL dp[N];
    int main() {
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i) {
            scanf("%lld%lld",&Q[i].x,&Q[i].y);
        }
        sort(Q+1,Q+n+1,cmp1);
        int cnt = 0;
        for(int i = 1; i <= n; ++i) {
            while(cnt && tmp[cnt].y<=Q[i].y)cnt--;
            tmp[++cnt] = Q[i];
        }
        n = cnt;
        for(int i = 1; i <= n; ++i) Q[i] = tmp[i],dp[i] = 1e15;
        dp[0] = 0;
        int l = 1,r = 2;q[1] = 0;
        q[2] = 1;dp[1] = 1LL*Q[1].x * Q[1].y;
        for(int i = 2; i <= n; ++i) {
            while(l < r && dp[q[l+1]] - dp[q[l]] < 1LL*(Q[q[l]+1].y - Q[q[l+1]+1].y) * Q[i].x) ++l;
            dp[i] = dp[q[l]] + 1LL*Q[i].x * Q[q[l]+1].y;
            while(l < r && (dp[q[r]]-dp[q[r-1]]) * 1LL*(Q[q[r]+1].y-Q[i+1].y) > (dp[i] - dp[q[r]]) * (Q[q[r-1]+1].y-Q[q[r]+1].y)) --r;
            q[++r] = i;
        }
        printf("%lld
    ",dp[n]);
        return 0;
    }
  • 相关阅读:
    mysql注入小测试
    让函数返回指定值实用写法
    源码下载网址
    带宽
    九度oj 题目1080:进制转换
    九度oj 题目1079:手机键盘
    poj 3046 Ant Counting
    整数拆分问题
    poj 2229 Sumsets
    九度oj 题目1411:转圈
  • 原文地址:https://www.cnblogs.com/zxhl/p/7634664.html
Copyright © 2011-2022 走看看