您的位置:首页 > 其它

A1251. 设计铁路(钱桥) DP+斜率优化

2016-04-23 19:30 211 查看
明明是一道裸题,我却做了这么久。感觉自己斜率优化真是弱啊,省选就没做出来,现在做还是这么费力。

我们用di,ai分别表示第i个车站到终点的距离和人数。

首先按照di降序排序,然后我们用fi表示在第i个村庄出修建一个车站,且1 i的所有人都开车到车站,此时的总花费。

然后我们维护两个前缀和si,pi。

si=∑j=i+1ndj∗aj

pi=∑j=i+1naj

那么状态转移方程如下:

fi=min{fj+m+sj−si−(pj−pi)×di}

把与j无关的量提到外面:

fi=min{fj+sj−pj×di}+m+pi×di−si

那么考虑若存在j<k,且k比j更优,那么有

fk+sk−pk×di<fj+sj−pj×di

化简可得

(fk+sk)−(fj+sj)pk−pj>di

然后就可以斜率优化了。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int N=40005;
int n,m;
struct node
{
int d,r;
}p
;
long long s
,g
,f
;
int q
;

inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}

inline bool operator<(node a,node b)
{
return a.d>b.d;
}

inline long long Y(int j,int k)
{
return f[j]+s[j]-f[k]-s[k];
}

inline long long X(int j,int k)
{
return g[j]-g[k];
}

int main()
{
n=read(); m=read();
for (int i=1;i<=n;i++)
p[i].d=read(),p[i].r=read();
sort(p+1,p+n+1);
for (int i=n-1;~i;i--)
s[i]=s[i+1]+p[i+1].d*p[i+1].r,g[i]=g[i+1]+p[i+1].r;
int t=0,w=0;
for (int i=1;i<=n+1;i++)
{
while (t<w&&Y(q[t+1],q[t])<X(q[t+1],q[t])*p[i].d) t++;
f[i]=f[q[t]]+s[q[t]]-s[i]+(g[i]-g[q[t]])*p[i].d+m;
while (t<w&&Y(i,q[w])*X(q[w],q[w-1])>Y(q[w],q[w-1])*X(i,q[w])) w--;
q[++w]=i;
}
cout << f[n+1]-m << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: