2018.09.07 codeforces311B. Cats Transport(斜率优化dp)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/82502135

传送门
斜率优化dp好题。
对于第i只猫,显然如果管理员想从出发开始刚好接到它,需要在 t [ i ] = h [ i ] d i s t ( 1 , i ) 的时候出发才行。
这样的话,如果把第l~r只猫分成一组,那么当前分组需要的最小花费是
t [ r ] t [ l ] + t [ r ] t [ l + 1 ] + t [ r ] t [ l + 2 ] + . . . + t [ r ] t [ r ] = t [ r ] ( r l + 1 ) ( s u m [ r ] s u m [ l 1 ] )
于是就可以推出状态转移方程了:
f [ i ] [ j ] = m i n ( f [ i 1 ] [ k ] + a [ j ] ( j k ) + ( s u m [ j ] s u m [ k ] ) )
对于两个不同的决策k1,k2。
如果k1转移出的结果比k2优秀,那么:
f [ i 1 ] [ k 1 ] + a [ j ] ( j k 1 ) + ( s u m [ j ] s u m [ k 1 ] ) < f [ i 1 ] [ k 2 ] + a [ j ] ( j k 2 ) + ( s u m [ j ] s u m [ k 2 ] )
=> ( ( f [ i 1 ] [ k 1 ] s u m [ k 1 ] ) ( f [ i 1 ] [ k 2 ] s u m [ k 2 ] ) ) < a [ j ] ( k 1 k 2 )
假设 t [ k ] = f [ i 1 ] [ k ] s u m [ k ]
=> ( t [ k 1 ] t [ k 2 ] ) / ( k 1 k 2 ) < a [ j ]
果断斜率优化了。
代码:

#include<bits/stdc++.h>
#define N 100005
#define ll long long
using namespace std;
inline ll read(){
    ll ans=0,w=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans*w;
}
int q[N],hd,tl,n,m,p,tmp;
ll dis[N],h[N],t[N],sum[N],f[2][N],ans=1e18;
inline ll gety(int k,int i,int j){return f[k][i]+sum[i]-f[k][j]-sum[j];}
inline ll getx(int i,int j){return i-j;}
int main(){
    n=read(),m=read(),p=read();
    for(int i=2;i<=n;++i)dis[i]=dis[i-1]+read();
    for(int i=1;i<=m;++i)tmp=read(),t[i]=read()-dis[tmp];
    sort(t+1,t+m+1);
    for(int i=1;i<=m;++i)sum[i]=sum[i-1]+t[i];
    fill(f[0]+1,f[0]+m+1,1e18);
    int las=0;
    for(int i=1;i<=p;++i){
        hd=tl=1,q[1]=0,las^=1;
        for(int j=1;j<=m;++j){
            while(hd<tl&&gety(las^1,q[hd+1],q[hd])<t[j]*getx(q[hd+1],q[hd]))++hd;
            int k=q[hd];
            f[las][j]=f[las^1][k]+t[j]*(j-k)-(sum[j]-sum[k]);
            while(hd<tl&&gety(las^1,q[tl],q[tl-1])*getx(j,q[tl])>gety(las^1,j,q[tl])*getx(q[tl],q[tl-1]))--tl;      
            q[++tl]=j;
        }
        ans=min(ans,f[las][m]);
    }
    cout<<ans;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/82502135