• [BZOJ1597]土地购买


    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

    Sample Output

    500

    HINT

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

    题解

    斜率优化好像是很久之前的坑?

    推式子真是太刺激了.

    对于这道题,购买的土地并不是连续的,所以原始数据并不具有决策单调性.

    所以我们需要通过某些操作,构造出一个决策单调性.

    有一种方法好像是用堆...?我本人是sort了一遍,按照第一关键字长度递增,第二关键字宽度递增.

    然后扫一遍,把小块放在大块中一起购买(相当于合并)

    这样最后得到的数据就有决策单调性了,因为这时连着买肯定比跳着买要优越

    然后我们再手推一下式子

    f[i]=f[j]+land[j+1].y*land[i].x

    对于某两个决策点j1,j2,如果j1优于j2

    f[j1]+land[j1+1].y*land[i].x<f[j2]+land[j2+1].y*land[i].x

    f[j1]-f[j2]<land[i].x*(land[j2+1].y-land[j1+1].y)

    (f[j1]-f[j2])/(land[j2+1].y-land[j1+1].y)<land[i].x

    设k(j1,j2)=(f[j1]-f[j2])/(land[j2+1].y-land[j1+1].y)

    那么我们用一个单调队列q[]来维护,

    设头为h,尾为t,则q[h+1]比q[h]优时,有k(q[h+1],q[h])<x[i],此时h++

    对于插入元素i,如果i比q[t]优,则k(i,q[t])<k(q[t],q[t-1]),此时t--

    然后照着打就行了,代码见下

     1 #include<cstdio>
     2 #include<queue>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long LL;
     7 const int N=50100;
     8 int n,e,q[N],head,tail;
     9 LL f[N];
    10 struct node{LL x,y;}land[N],s[N];
    11 inline bool mt(const node &a,const node &b){return a.x==b.x?a.y<b.y:a.x<b.x;}
    12 inline double k(int j1,int j2){return (double)(f[j1]-f[j2])/(s[j2+1].y-s[j1+1].y);}
    13 int main()
    14 {
    15     scanf("%d",&n);
    16     for(int i=1;i<=n;i++)
    17         scanf("%lld%lld",&land[i].x,&land[i].y);
    18     sort(land+1,land+n+1,mt);
    19     for(int i=1;i<=n;i++)
    20     {
    21         while(e&&land[i].y>=s[e].y)e--;
    22         s[++e]=land[i];
    23     }
    24     for(int i=1;i<=e;i++)
    25     {
    26         while(head<tail&&k(q[head+1],q[head])<s[i].x)head++;
    27         f[i]=f[q[head]]+s[q[head]+1].y*s[i].x;
    28         while(head<tail&&k(i,q[tail])<k(q[tail],q[tail-1]))tail--;
    29         q[++tail]=i;
    30     }
    31     printf("%lld",f[e]);
    32 }
    BZOJ1597
    Progress is not created by contented people.
  • 相关阅读:
    URL域名获取
    SQL Server 索引结构及其使用(二)
    SQL Server 索引结构及其使用(一)[转]
    查询数据库中所有表的数据量、有效数据量以及其它定制数据量
    转:Servlet的url匹配以及url-pattern详解
    转:在MyEclipse下创建Java Web项目 入门(图文并茂)经典教程
    MyEclipse +Servlet 乱码
    MyEclipse +Tomcat 异常操作
    Android Include标签
    转ATL对象类型
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7007015.html
Copyright © 2020-2023  润新知