正题
luogu-CF 311B
题目大意
有n个点,p个铲屎官和m只猫
did_idi表示i到i-1的距离
第i只猫在tit_iti这个时间hih_ihi这个点开始等待铲屎官来接它走
铲屎官会以一个单位时间走一个单位长度的速度从第一个点向最后一个点走(不能停止),当他走到点i时,若这里有猫在等,那他就会接走他
现在让你来安排各个铲屎官的出发时间,使得每只猫等待时间之和最小
解题思路
设fi,jf_{i,j}fi,j为i个铲屎官接前j只猫的最小等待时间之和
那么有:
fi,j=min{fi−1,k+∑c=k+1j(tj−tc)}=min{fi−1,k+∑c=k+1jtj−∑c=k+1jtc}=min{fi−1,k+t[j]∗(j−k)−sumtj+sumtk}=min{fi−1,k+tj∗j−tj∗k−sumtj+sumtk}\begin{aligned} f_{i,j} & = min\{f_{i - 1,k}+\sum_{c = k+1}^{j}(t_j-t_c)\} \\ & = min\{f_{i - 1,k}+\sum_{c = k+1}^{j}t_j - \sum_{c = k+1}^{j}t_c\} \\ & = min\{f_{i-1,k} + t[j]*(j-k) - sumt_j + sumt_k\} \\ & = min\{f_{i-1,k} + t_j*j - t_j*k - sumt_j + sumt_k\} \end{aligned}fi,j=min{fi−1,k+c=k+1∑j(tj−tc)}=min{fi−1,k+c=k+1∑jtj−c=k+1∑jtc}=min{fi−1,k+t[j]∗(j−k)−sumtj+sumtk}=min{fi−1,k+tj∗j−tj∗k−sumtj+sumtk}
对于决策点a、b,如果a>b,且a比b优,那么有:
fi−1,a+tj∗j−tj∗a−sumtj+sumta<fi−1,b+tj∗j−tj∗b−sumtj+sumtbfi−1,a−tj∗a+sumta<fi−1,b−tj∗b+sumtb(fi−1,a+sumta)−(fi−1,b+sumtb)a−b<tj\begin{aligned} \\ f_{i-1,a} + t_j*j - t_j*a - sumt_j + sumt_a &< f_{i-1,b} + t_j*j - t_j*b - sumt_j + sumt_b \\ f_{i-1,a} - t_j*a + sumt_a &< f_{i-1,b} - t_j*b + sumt_b \\ \frac{(f_{i-1,a}+sumt_a)-(f_{i-1,b}+sumt_b)}{a-b}&<t_j\end{aligned}fi−1,a+tj∗j−tj∗a−sumtj+sumtafi−1,a−tj∗a+sumtaa−b(fi−1,a+sumta)−(fi−1,b+sumtb)<fi−1,b+tj∗j−tj∗b−sumtj+sumtb<fi−1,b−tj∗b+sumtb<tj
然后带入模板即可
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll ww, n, m, c, xx, yy, w[100010], t[100010], l[100010], r[100010], sumt[100010], x[110][100010], f[110][100010];
int d[110][100010];
int main()
{scanf("%lld%lld%lld", &ww, &n, &m);for (ll i = 2; i <= ww; ++i){scanf("%lld", &w[i]);w[i] += w[i - 1];}for (ll i = 1; i <= n; ++i){scanf("%lld%lld", &xx, &yy);t[i] = yy - w[xx];//计算出铲屎官的出发时间}sort(t+1, t+1+n);for (ll i = 1; i <= n; ++i)sumt[i] = sumt[i - 1] + t[i];for (ll i = 1; i <= m; ++i)for (ll j = 1; j <= n; ++j){c = i - 1;while(l[c] < r[c] && x[c][d[c][l[c] + 1]] - x[c][d[c][l[c]]] < t[j] * (d[c][l[c] + 1] - d[c][l[c]])) l[c]++;f[i][j] = f[c][d[c][l[c]]] + t[j] * (j - d[c][l[c]]) - sumt[j] + sumt[d[c][l[c]]];x[i][j] = f[i][j] + sumt[j];while(l[i] < r[i] && (x[i][j]-x[i][d[i][r[i]]])*(d[i][r[i]]-d[i][r[i] - 1]) < (x[i][d[i][r[i]]]-x[i][d[i][r[i] - 1]])*(j-d[i][r[i]])) r[i]--;d[i][++r[i]] = j;}printf("%lld", f[m][n]);return 0;
}