正题
题目链接:https://www.luogu.com.cn/problem/CF311B
题目大意
nnn座山在一条线上,有mmm只猫,第iii只从tit_iti开始在第xix_ixi座山上游玩结束。
派ppp个人在不同时间从111走到nnn接走所有游玩结束的猫,求所有猫的最小等待时间。
解题思路
对于一只猫iii,就是要求从ti−∑j=1xidjt_i-\sum_{j=1}^{x_i}d_jti−∑j=1xidj时刻出发才可以接到。后文直接让ti=ti−∑j=1xidjt_i=t_i-\sum_{j=1}^{x_i}d_jti=ti−∑j=1xidj。排序后求一个前缀和sss以方便后面计算。
那么我们肯定是直接接连续的一段tit_iti来接,我们设fi,jf_{i,j}fi,j表示到第iii个人,接送了前jjj只猫时的最小等待时间和。那么有转移方程fi=min{fj+ti(i−j)−(si−sj)}f_i=min\{f_{j}+t_i(i-j)-(s_i-s_j)\}fi=min{fj+ti(i−j)−(si−sj)}
fi−si−tii=fj−tij+sjf_i-s_i-t_ii=f_j-t_ij+s_jfi−si−tii=fj−tij+sj
设两个j,k(j>k)j,k(j>k)j,k(j>k)中的jjj优于kkk
fj−tij+sj<fk−tik+skf_{j}-t_ij+s_j<f_k-t_ik+s_kfj−tij+sj<fk−tik+sk
设zi=fi+siz_i=f_i+s_izi=fi+si
zj−zk<ti(j−k)z_j-z_k<t_i(j-k)zj−zk<ti(j−k)
zj−zkj−k<ti\frac{z_j-z_k}{j-k}<t_ij−kzj−zk<ti
斜率优化即可,时间复杂度O(np)O(np)O(np)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10;
ll n,m,p,d[N],t[N],f[101][N],s[N],z[N],q[N];
int main()
{scanf("%lld%lld%lld",&n,&m,&p);for(ll i=2;i<=n;i++)scanf("%lld",&d[i]),d[i]+=d[i-1];for(ll i=1;i<=m;i++){ll x;scanf("%lld%lld",&x,&t[i]);t[i]-=d[x];}sort(t+1,t+1+m);memset(f,0x3f,sizeof(f));f[0][0]=0;for(ll i=1;i<=m;i++)s[i]=s[i-1]+t[i];for(ll i=1;i<=p;i++){ll l=1,r=1;q[1]=0;for(ll j=1;j<=m;j++)z[j]=f[i-1][j]+s[j];for(ll j=1;j<=m;j++){while(l<r&&z[q[l+1]]-z[q[l]]<=t[j]*(q[l+1]-q[l]))l++;f[i][j]=min(f[i-1][j],z[q[l]]-s[j]+(j-q[l])*t[j]); if(z[j]>=0x3f3f3f3f3f3f3f3fll)continue;while(l<r&&(z[j]-z[q[r]])*(q[r]-q[r-1])<=(z[q[r]]-z[q[r-1]])*(j-q[r]))r--;q[++r]=j;}}printf("%lld",f[p][m]);return 0;
}