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

    1597: [Usaco2008 Mar]土地购买

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3601  Solved: 1322

    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

    FJ分3组买这些土地: 第一组:100x1, 第二组1x100, 第三组20x5 和 15x15 plot. 每组的价格分别为100,100,300, 总共500.

    【分析】

       

      因为要买所有土地,所以如果一个矩形完全被另一个矩形包含,那么可以不考虑小的那个矩形。

      去掉他们只有按照长x升序排序,可以发现宽y都是降序的(不然会被去掉),所以容易知道我们每次取的一组都是连续的一段。

      设答案为f[i]

      则f[i]=x[i]*y[j+1]+f[j] 得到斜率优化标准式子,维护一个左下凸包。

    代码如下:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<cmath>
     8 using namespace std;
     9 #define Maxn 50010
    10 #define LL long long
    11 
    12 struct hp
    13 {
    14     LL x,y;
    15 }a[Maxn];
    16 
    17 bool cmp(hp x,hp y) {return (x.x==y.x)?(x.y<y.y):(x.x<y.x);}
    18 
    19 struct node
    20 {
    21     LL x,y;
    22 }t[Maxn];
    23 
    24 LL f[Maxn];
    25 
    26 bool check(int x,int y,int k)
    27 {
    28     LL kk=k;
    29     return kk*(t[x].x-t[y].x)<=t[x].y-t[y].y;
    30 }
    31 
    32 bool check2(int x,int y,int z)
    33 {
    34     return (t[y].x-t[z].x)*(t[x].y-t[y].y)<=(t[x].x-t[y].x)*(t[y].y-t[z].y);
    35 }
    36 
    37 int main()
    38 {
    39     int n;
    40     scanf("%d",&n);
    41     for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
    42     sort(a+1,a+1+n,cmp);
    43     int cnt=0;
    44     for(int i=1;i<=n;i++)
    45     {
    46         while(cnt>0&&a[i].y>=a[cnt].y) cnt--;
    47         a[++cnt]=a[i];
    48     }
    49     int len=0,st;
    50     t[++len].x=a[1].y;t[len].y=0;st=1;
    51     for(int i=1;i<=cnt;i++)
    52     {
    53         while(st<len&&check(st,st+1,-a[i].x)) st++;
    54         f[i]=a[i].x*t[st].x+t[st].y;
    55         t[0].x=a[i+1].y;t[0].y=f[i];
    56         while(st<len&&check2(len-1,len,0)) len--;
    57         t[++len]=t[0];
    58     }
    59     printf("%lld
    ",f[cnt]);
    60     return 0;
    61 }
    [BZOJ 1597]

    2016-09-19 20:15:26

  • 相关阅读:
    Docker安装Redis
    C语言读取Java的字节码文件的第一步
    springdataredis之RedisMessageListenerContainer源码解析
    【转载】logback自定义目录及输出格式
    【转载】springbootdependencies 跟 springbootstarterparent
    Docker安装PostgreSQL数据库
    SpringBoot整合Redis实现发布订阅功能实践
    iso 刻录软件 openwrt
    python selenium 获取UA 睁yan
    cnvd 获取最新cookie (反爬) 睁yan
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5886483.html
Copyright © 2011-2022 走看看