zoukankan      html  css  js  c++  java
  • 【bzoj1597- [Usaco2008 Mar]土地购买】斜率优化

    597[Usaco2008 Mar]土地购买

    【题目描述】

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

    【输入格式】

    1: 一个数: N

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

    【输出格式】

    求最小的可行费用。

    Sample Input

    4

    100 1

    15 15

    20 5

    1 100

    Sample Output

    500

    HINT

    FJ3组买这些土地: 第一组:100×1, 第二组1×100, 第三组20×5 15×15 plot. 每组的价格分别为100,100,300, 总共500

     

    给定一些矩形,分组购买,一组的价格是其中最大的长*最大的宽。

    n<=50000

     

    一开始并没有思路。。。

     

    首先,我们考虑没有贡献的矩形——对于x,如果存在a[y]>=a[x] && b[y]>=b[x],则x是无用的。排序去掉。

    排序就先按x排序大到小,再按y排序大到小。

    出现排序后x,y,z矩形,x能不能套y但能套z的话,那y也能套z,是不会错的。。 

    最后一定是a递减,b递增。


    so:

    f[i]=f[j]+a[j+1]*b[i]

    然后用斜率优化。

    这个是把除法改成乘法的。

     

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<algorithm>
     7 #include<queue>
     8 using namespace std;
     9 
    10 typedef long long LL;
    11 const int N=50010;
    12 int n,pl,Q[N];
    13 LL l=0,r=0,ai,xj,bj,j,f[N];
    14 struct node{
    15     LL a,b;
    16     bool bk;
    17 }p[N];
    18 
    19 // f[i]=f[j]+a[j+1]*b[i]
    20 // ai=b[i]
    21 // xj=a[j+1]
    22 // bj=f[j]
    23 
    24 LL XX(int i,int j){return p[i+1].a-p[j+1].a;}
    25 LL YY(int i,int j){return f[i]-f[j];}
    26 double X(int i){return p[i+1].a;}
    27 double Y(int i){return f[i];}
    28 double find_k(int i,int j){return (Y(i)-Y(j))/(X(i)-X(j));}
    29 
    30 bool cmp(node x,node y){
    31     if(x.a!=y.a) return x.a>y.a;
    32     return x.b>y.b;
    33 }
    34 
    35 bool judge_1()
    36 {
    37     LL tx=XX(Q[l],Q[l+1]),ty=YY(Q[l],Q[l+1]);
    38     if(tx>=0) return ty>=((-ai)*tx);
    39     return ty<=((-ai)*tx);
    40 }
    41 
    42 bool judge_2(int i)
    43 {
    44     LL t0=YY(Q[r],Q[r-1]),t1=XX(Q[r],Q[r-1]),t2=YY(i,Q[r]),t3=XX(i,Q[r]);
    45     if(t1<0) t0=-t0,t1=-t1;
    46     if(t3<0) t2=-t2,t3=-t3;
    47     return (t0*t3)<(t1*t2);
    48 }
    49 
    50 int main()
    51 {
    52     freopen("a.in","r",stdin);
    53     // freopen("acquire.in","r",stdin);
    54     // freopen("acquire.out","w",stdout);
    55     scanf("%d",&n);
    56     for(int i=1;i<=n;i++) 
    57     {
    58         scanf("%lld%lld",&p[i].a,&p[i].b);
    59         p[i].bk=1;
    60     }
    61     sort(p+1,p+1+n,cmp);
    62     j=1;
    63     for(int i=2;i<=n;i++)
    64     {
    65         if(p[i].a<=p[j].a && p[i].b<=p[j].b) p[i].bk=0;
    66         else j=i;
    67     }
    68     pl=1;
    69     for(int i=2;i<=n;i++)
    70         if(p[i].bk) p[++pl]=p[i];
    71 
    72     for(int i=1;i<=pl;i++)
    73     {
    74         ai=p[i].b;
    75         while(l<r && judge_1()) l++;/*find_k(Q[l],Q[l+1])>=(-ai)*/
    76         j=Q[l];
    77         xj=p[j+1].a;
    78         bj=f[j];
    79         f[i]=ai*xj+bj;
    80         while(l<r && judge_2(i)) r--;/*find_k(Q[r],Q[r-1])<find_k(i,Q[r])*/
    81         Q[++r]=i;
    82     }
    83     printf("%lld
    ",f[pl]);
    84     return 0;
    85 }

     

  • 相关阅读:
    drf 02 APIView的请求生命周期及各个模块源码分析和配置
    drf 03 序列化模块
    Django-restframework框架01
    javascript深入理解闭包(转)
    从经典问题来看 Copy 方法(转)
    JavaScript要点(七) 函数调用
    关于iOS中SQLITE句柄的使用的细节
    Xcode8 创建NSManageObject subclass方法
    JavaScript要点 (六) 函数参数
    JavaScript要点 (五) 函数定义
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5890544.html
Copyright © 2011-2022 走看看