BZOJ 1597 土地购买 斜率优化

首先,我们看啊,这道题是把线性序列分段的问题,于是显然需要用DP

(^o^)/YES!

于是,f[i]就代表购买前i块土地所需要的最小费用

那么我们就来思考方程,但是发现可能需要我们先来排一排序,搞一搞就出来方程了

于是我们把length升序排列,放到一个队列中

这时我们发现有这样一种现象

存在land[i].length>=land[j].length&&land[i].width>=land[j].width那么j完全没有存在的必要(j表示我好伤心~~(>_<)~~),但是不管你伤不伤心我们都要删去j

这样之后,我们就会发现排完序后length按照升序排列,width一定按照降序排列(你自己YY吧)

那么显然DP方程就是f[i]=min(f[i],f[j]+land[j+1].width*land[i].length)

(⊙v⊙)嗯,看起来很对的样子

(^o^)/YES!

等等,但是你有没有发现这是一个n^2的算法,而n最大为50000,(⊙v⊙)嗯……炸了>o<

看起来nlgn还是可以接受的

那么我们就需要优化一下啦

O(∩_∩)O哈哈~

锵锵锵,斜率优化闪亮登场

f[i]=f[j]+land[j+1].width*land[i].length

-land[i].length*land[j+1].width+f[i]=f[j]

-land[i].length就代表斜率,f[i]代表截距,那么(land[j+1].width,f[j])就可以看作关于i的点集中的j点

因为我们要求最小值,也就是求最小截距,于是我们就有这样一条截距为-land[i].length的直线,然后有一堆点,如果一个一个枚举就,就,炸了 >o<……

所以呢,我们要维护一个单调队列,使得斜率单调递增

然后我们看这样一种现象

设在当前状态f[i]时,从f[j]转移比从f[k]转移更优,那么f[j]+land[j+1].width*land[i].length

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
const int maxn=50000+10;
struct field{
    LL length,width;
}land[maxn],land2[maxn];
LL n,f[maxn],q[maxn];
bool cmp(field a,field b){
    return a.length<b.length||a.length==b.length&&a.width>b.width;//使长单调上升
}
int main(){
    cin>>n;
    for(LL i=1;i<=n;i++)
        scanf("%d%d",&land[i].length,&land[i].width);
    sort(land+1,land+n+1,cmp);
    LL tail=1;
    land2[1].length=land[1].length,land2[1].width=land[1].width;
    for(LL i=2;i<=n;i++){
        while(tail&&land[i].width>land2[tail].width)
            tail--;
        land2[++tail].length=land[i].length,land2[tail].width=land[i].width;
    }
    memset(f,0x3f,sizeof(f));
    LL hd=1,ta=1;
    q[1]=0,f[0]=0;
    for(int i=1;i<=tail;i++){
        while((hd<ta)&&(land2[i].length*(land2[q[hd]+1].width-land2[q[hd+1]+1].width)>f[q[hd+1]]-f[q[hd]]))
            hd++;
        f[i]=f[q[hd]]+land2[q[hd]+1].width*land2[i].length;
        while((hd<ta)&&(f[i]-f[q[ta-1]])*(land2[q[ta]+1].width-land2[i+1].width)>=(f[i]-f[q[ta]])*(land2[q[ta-1]+1].width-land2[i+1].width))
            ta--;
        q[++ta]=i;
    }
    cout<<f[tail]<<endl;
    return 0;
}


by >o< neighthorn

时间: 2024-08-23 15:58:01

BZOJ 1597 土地购买 斜率优化的相关文章

bzoj 1597 [Usaco2008 Mar]土地购买——斜率优化dp

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1597 又一道斜率优化dp.负数让我混乱.不过仔细想想还是好的. 还可以方便地把那个负号放到x上.只要改一下slope里的一个负号,就变成正常舒服的递增了. 这道题的要点其实是一开始h=0.不能h=1.这样就能把dp[0]纳入考虑.这是需要的. #include<iostream> #include<cstdio> #include<cstring> #includ

BZOJ 1597 Usaco 2008 Mar 土地购买 斜率优化DP

题目大意:给出一些木板,现在要购买这些木板.购买的规则是可以一些木板一起买,然后价格是最大的长度乘最大的宽度.求购买所有木板的最小费用. 思路:如果一个木板的长也比一个木板小,宽也比一个木板小,那么这个木板就可以被排除.把所有木板按照x的长度排序,然后去掉排除的木板,然后剩下的木板就是x值下降, y值上升的木板.这样的话我们买下连续的一段的费用就是x[j] * y[i],然后DP方程就很简单了:f[i] = f[j] - x[j + 1] * y[i]. 注意到数据范围,写一个斜率优化就水过了.

【BZOJ1597】【Usaco2008 Mar】土地购买 斜率优化DP

题解:首先将块排个序,然后去掉被其它某块包含的块,然后斜率优化dp dp方程:f[i]=f[j]+a[i]*b[j+1]; 具体什么x啊y啊什么的在代码注释里面. --....纠结死了.开始各种WA,现在才发现: inline long long xmul(Point i,Point j,Point k){(i.y-j.y)*(j.x-k.x)-(j.y-k.y)*(i.x-j.x);} 上面的代码竟然能通过编译--,无力吐槽.以后一定要用终端+Wall命令编译文件了. warning一日不死,

BZOJ 1597 土地购买

斜率优化... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 50050 #define inf 0x7f7f7f7f7f7f7f7fLL using namespace std; long long n,s[maxn],top=0,f[maxn],g[maxn],a[maxn],b[maxn],l,r,q[maxn]; struc

bzoj1597/luogu2900 土地购买 (斜率优化dp)

首先按x从小到大排序,那么可得: f[i]=min{f[j]+x[i]*maxy[j+1..i]} 然而这样是$O(n^2)$的而且无法做优化. 然后我们考虑:如果对于某一点,存在另一点的x和y都比它大,那这个点是可以删掉不参与计算的(因为那个较大的点一定要被买,那只要把这两点放在一组里,较小的点是绝对不会被算到的) 然后就可以发现,随着x[i]单调增,y[i]是单调减的 那刚才的式子就可以变成f[i]=min{f[j]+x[i]*y[j+1]}了,于是就可以做斜率优化了. 1 #include

BZOJ 1010 玩具装箱 斜率优化DP

详情见 http://www.cnblogs.com/proverbs/archive/2013/02/01/2713109.html(我觉得这里面讲得已经够详细了,我就不赘述了) 还是来回忆一下做这道题的历程吧!一开始的确有点想错了,但马上又反应过来,清楚了题意.写了个 n^2 的算法.很明显,对于n <=  50000 的数据,肯定是要TLE的.(援引我看博客过程中看到的一句话来形容就是“省选题的数据就是硬”.)没办法,只能上网找百度(太弱了).一开始的确有点茫然,但马上就决定要自己推导一下

bzoj 1957 土地购买

这道题是我斜率优化第一题,对此做一个纪念. 首先进行一遍筛选,然后动态规划表达式很快就写出来了f(i)=min(f(i)+b[j+1]*a[i]) 然后就要进行斜率优化了,显然这里边所有东西都是单调的,所以只需要维护单调队列即可. cal函数计算的是斜率,具体看代码吧(参考别人),以后要多加练习. 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5

bzoj 1096 仓库建设 -斜率优化

L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏.由于地形的不同,在不同工厂建立仓库的费用可能是不同的.第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci.对于没有建立仓库的工厂,其产品应被运往其他的仓库进行储藏,而由于L公司产品的对外

bzoj 4518 [Sdoi2016]征途 (斜率优化DP)

我犯了sb错误然后调了1个小时......队列写错了 斜率k递增,b取最小值,队列维护凸包即可 f[0]的预处理好像有些奇怪???我把inf调大就过了??? 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #define il inline 5 #define ll long long 6 #define N 3010 7 #define inf 66666666 8 using nam