• [斜率优化][DP]luogu P2900 [USACO08MAR]Land Acquisition G


    题面

    https://www.luogu.com.cn/problem/P2900

    分析

    首先把长宽同时小于等于别人的土地除去,因为买下它的代价必然可以被覆盖

    可以用按 w,l 双关键字降序排序除去,除完以后发现此时 w 单调递减 l 单调递增

    考虑转移方程 $f[i]=min(f[j]+w[j]*l[i])(1<=j<i)$

    这个是一个很显然的斜率优化方程形式,则若 $1leq j < k < i$ ,若 j 比 k 更优

    $f[j]+w[j+1]*l[i] < f[k]+w[k+1]*l[i]$

    $f[j]-f[k]<l[i]*(w[k+1]-w[j+1])$

    $frac{f[j]-f[k]}{w[k+1]-w[j+1]}>l[i]$

    单调队列优化一下即可

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int N=5e4+10;
    struct Rect {
        ll w,l;
    }a[N];
    int n,m,h,t,q[N];
    ll f[N];
    
    bool CMP(Rect a,Rect b) {return a.w>b.w||a.w==b.w&&a.l>b.l;}
    
    double Slope(int i,int j)  {return (f[i]-f[j])/(a[j+1].w-a[i+1].w);}
    
    int main() {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%lld%lld",&a[i].w,&a[i].l);
        sort(a+1,a+n+1,CMP);
        for (int i=1;i<=n;i++) if (a[m].l<a[i].l) a[++m]=a[i];
        h=t=1;
        for (int i=1;i<=m;i++) {
            while (h<t&&Slope(q[h],q[h+1])<=a[i].l) h++;
            f[i]=f[q[h]]+a[q[h]+1].w*a[i].l;
            if (i==m) break;
            while (h<t&&Slope(q[t-1],q[t])>=Slope(q[t],i)) t--;
            q[++t]=i;
        }
        printf("%lld",f[m]);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    node连接mysql数据库
    mysql重置密码
    CSS vertical-align 属性
    JS中常用的字符串方法
    JS中的常用数组方法
    获取下拉菜单中具有SELECTED属性元素的序号和值的方法
    基本的正则表达式符号
    让多个文本输入框左侧对齐方法
    CSS选择器权重对比
    让内联元素支持宽高的几个设置
  • 原文地址:https://www.cnblogs.com/mastervan/p/14594053.html
Copyright © 2020-2023  润新知