码迷,mamicode.com
首页 > 其他好文 > 详细

CF331B Cats Transport[斜率优化dp+贪心]

时间:2019-03-02 18:29:17      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:根据   \n   怎么   long   最优   std   sum   优化   org   

luogu翻译

一些山距离起点有距离且不同,m只猫要到不同的山上去玩ti时间,有p个铲屎官人要去把所有猫接走,步行速度为1单位每秒,从1走到N座山不停下,必须在猫玩完后才可以把他带走。可以提前出发。问所有猫最少等待时间之和。


 

这题一开始有个模糊想法就是$f[i][j]$表示前i个人接j只猫,但是猫是乱序的,必须找一种方法顺序的dp。想到排序。但是排时间抑或是距离都不对,要考虑优先接哪个。然后瞎想到每只猫可以让人在$T_i-dis_i$时刻从起点出发正好接到不用等,那接一堆猫等待时间取决于要求出发最迟的那只猫。把每只猫正好接到要求的出发时间做一下从小到大排个序,一个人接某批猫,每只猫的等待时间就是最大出发时间减去接这只猫的出发时间。然后考虑在这上面dp。然而选的猫不一定连续。可以证明(怎么证?我也不会),只有每个人接这里面连续的一批猫才有可能产生最优解。可以意会一下,我原来连续的一段,中间有一个给下一个人带走,等待时间更长,给上一个人带走,差不多、大概、应当也不优。实在不行可以打表看一下,比较其他划分有没有比连续划分优的。反正我是根据类似经历感觉出来的。

然后方程很好写,区间划分。sum是等待时间前缀和,方便转移。a是等待时间,注意在排完序后就单调了。

$f[i][j]=min{f[i-1][k]+(j-k)*a[j]-(sum[j]-sum[k])}   i<=j<=n  i-1<=k<j$

然后拆开写斜截式,搞搞就斜率优化维护下凸壳,又斜率单调增,所以上述$O(pm^2)$化为$O(pm)$

$f[i-1][k]+sum[k]=a[j]*k+j*a[j]+f[i][j]+sum[j]$


记下错误:

初始化又错!初始化又错!初始化又错!LINE23.真的不能再犯了。。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
 5 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
 6 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
 7 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
 8 template<typename T>inline T read(T&x){
 9     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c==-)f=1;
10     while(isdigit(c))x=x*10+c-0,c=getchar();return f?x=-x:x;
11 }
12 const int N=100000+7;
13 ll f[103][N],d[N],a[N],sum[N],hi,ti;
14 int q[N];
15 int n,m,p,l,r;
16 inline ll y(int k,int i){return f[i-1][k]+sum[k];}
17 
18 int main(){//freopen("test.in","r",stdin);//freopen("tmp.out","w",stdout);
19     read(n),read(m),read(p);if(p>=m)return printf("0\n"),0;
20     for(register int i=2;i<=n;++i)d[i]=read(d[i])+d[i-1];
21     for(register int i=1;i<=m;++i)read(hi),read(ti),a[i]=ti-d[hi];
22     sort(a+1,a+m+1);
23     for(register int i=1;i<=m;++i)sum[i]=a[i]+sum[i-1],f[1][i]=i*1ll*a[i]-sum[i];//MISTAKES! 
24     for(register int i=2;i<=p;++i){
25         q[l=r=1]=i-1;
26         for(register int j=i;j<=m;++j){
27             while(l<r&&y(q[l+1],i)-y(q[l],i)<=(q[l+1]-q[l])*1ll*a[j])++l;
28             f[i][j]=f[i-1][q[l]]+(j-q[l])*1ll*a[j]-sum[j]+sum[q[l]];
29             while(l<r&&(y(q[r],i)-y(q[r-1],i))*(j-q[r])>=(y(j,i)-y(q[r],i))*(q[r]-q[r-1]))--r;
30             q[++r]=j;
31         }
32     }
33     printf("%I64d\n",f[p][m]);
34     return 0;
35 }

 

CF331B Cats Transport[斜率优化dp+贪心]

标签:根据   \n   怎么   long   最优   std   sum   优化   org   

原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10462237.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!