【JZOJ5415】【NOIP2017提高A组集训10.22】[斜率优化]公交运输

Description

城市中有一条长度为n的道路,每隔1的长度有一个公交车站,编号从0到n,学校在0号车站的位置。其中每个公交车站(除了n号车站)有两个属性ci和vi,代表从这个公交车站出发的公交车的性质。ci代表这个从i出发的公交车,相邻两个停靠站之间的距离。vi表示每坐1站的花费。
注意,一辆公交车出发后会向n号车站的方向行进。同时,一名乘客只能从起点站上车,但可以从任意停靠站下车。校庆志愿者小Z为了帮助校友查询有关城市交通费用的问题,想知道从0号车站(也就是学校)出发,到达每个公交车站的最小花费,于是他找到了你。

Data Constraint

对于30%的数据满足,1<=n<=5000
对于60%的数据满足,1<=n<=10^5
对于另20%的数据满足,maxc=1
对于100%的数据满足,1<=n<=10^6,1<=maxc<=10,1<=ci<=maxc,1<=vi<=1000
数据存在梯度。

Solution

我们发现maxc<=10,把公交车放入[ci,i%ci]位置即可。但现在问题是dp不满足斜率优化。于是我们发现f[i]=min(f[i],f[j]+v[i]* (j-i)),f[i]=min(f[i],f[j]-v[i]*i+v[i]*j),设g[i]=f[i]-v[i]*i,那么这就像一个y=v[i]*x+g[i]的直线。对于每个[i,j]维护一个v单调递增的单调栈,同时若发现栈顶直线与栈顶下一条直线的交点在当前加入直线与栈顶直线的交点之前,那么说明栈顶不会优秀或者栈顶被栈顶下一条直线超越,则剔除栈顶。这样做是O(N)的.

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e6+5,maxn1=1e3;
int l[maxn+5],d[11][11],f[maxn],v[maxn];
int n,m,i,t,j,k,x,y,z,p;
int get(){
    char ch=getchar();int x=0;
    while (ch<48 || ch>57) ch=getchar();
    while (ch>=48 && ch<=57) x=x*10+ch-48,ch=getchar();
    return x;
}
int pan(int x,int y){
    return (f[y]-f[x])/(v[x]-v[y]);
}
int main(){
    freopen("bus.in","r",stdin);freopen("bus.out","w",stdout);
    scanf("%d%d",&n,&m);
    memset(l,255,sizeof(l));memset(d,255,sizeof(d));
    for (i=0;i<=n;i++){
        if (i!=n)x=get(),y=get();v[i]=y;
        z=1e9;
        for (j=1;j<=m;j++){
            while (l[d[j][i%j]]!=-1 && f[d[j][i%j]]+i/j*v[d[j][i%j]]>f[l[d[j][i%j]]]+i/j*v[l[d[j][i%j]]])
                d[j][i%j]=l[d[j][i%j]];
            if (d[j][i%j]!=-1)z=min(z,f[d[j][i%j]]+i/j*v[d[j][i%j]]);
        }
        if (z==1e9 && i) printf("-1 ");
        else{
            if (!i) z=0;
            else printf("%d ",z);
            f[i]=z-(i/x)*y;
            while (d[x][i%x]!=-1 && v[d[x][i%x]]>=v[i]) d[x][i%x]=l[d[x][i%x]];
            while (d[x][i%x]!=-1 && l[d[x][i%x]]!=-1 && pan(d[x][i%x],l[d[x][i%x]])<pan(i,d[x][i%x]))d[x][i%x]=l[d[x][i%x]];
            l[i]=d[x][i%x];d[x][i%x]=i;
        }
    }
}
发布了257 篇原创文章 · 获赞 451 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/crybymyself/article/details/78347000