版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/82502135
传送门
斜率优化dp好题。
对于第i只猫,显然如果管理员想从出发开始刚好接到它,需要在
的时候出发才行。
这样的话,如果把第l~r只猫分成一组,那么当前分组需要的最小花费是
于是就可以推出状态转移方程了:
对于两个不同的决策k1,k2。
如果k1转移出的结果比k2优秀,那么:
=>
假设
=>
果断斜率优化了。
代码:
#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;
}