运输小猫

小S是农场主,他养了 M 只猫,雇了 P 位饲养员。

农场中有一条笔直的路,路边有 N 座山,从 1 到 N 编号。

第 i 座山与第 i-1 座山之间的距离为 Di。

饲养员都住在 1 号山。

有一天,猫出去玩。

第 i 只猫去 Hi 号山玩,玩到时刻 Ti 停止,然后在原地等饲养员来接。

饲养员们必须回收所有的猫。

每个饲养员沿着路从 1 号山走到 N 号山,把各座山上已经在等待的猫全部接走。

饲养员在路上行走需要时间,速度为1 米/单位时间。

饲养员在每座山上接猫的时间可以忽略,可以携带的猫的数量为无穷大。

例如有两座相距为 1 的山,一只猫在 2 号山玩,玩到时刻 3 开始等待。

如果饲养员从 1 号山在时刻 2 或 3 出发,那么他可以接到猫,猫的等待时间为 0 或 1。

而如果他于时刻 1 出发,那么他将于时刻 2 经过 2 号山,不能接到当时仍在玩的猫。

你的任务是规划每个饲养员从 1 号山出发的时间,使得所有猫等待时间的总和尽量小。

饲养员出发的时间可以为负。

输入格式
第一行包含三个整数N,M,P。

第二行包含n-1个整数,D2,D3,…,DN。

接下来M行,每行包含两个整数Hi和Ti。

输出格式
输出一个整数,表示所有猫等待时间的总和的最小值。

数据范围
2≤N≤105,
1≤M≤105,
1≤P≤100,
1≤Di<1000,
1≤Hi≤N,
0≤Ti≤109

输入样例:
4 6 2
1 3 5
1 0
2 1
4 9
1 10
2 10
3 12
输出样例:
3
#include<bits/stdc++.h>

#define ll long long
using namespace std;
const int M = 105, N = 1e5 + 10;
ll f[M][N], t[N], s[N], d[N], g[N];
int q[N], n, m, p;

int main() {
    scanf("%d%d%d", &n, &m, &p);
    for (int i = 2; i <= n; i++)
        scanf("%lld", &d[i]), d[i] += d[i - 1];
    for (int i = 1, h; i <= m; i++)
        scanf("%d%lld", &h, &t[i]), t[i] -= d[h];
    sort(t + 1, t + 1 + m);
    for (int i = 1; i <= m; i++)s[i] = s[i - 1] + t[i];
    memset(f, 0x3f, sizeof(f)), f[0][0] = 0;
    for (int i = 1; i <= p; i++) {
        int l = 1, r = 1;
        q[1] = 0;
        for (int j = 1; j <= m; j++)g[j] = f[i - 1][j] + s[j];
        for (int j = 1; j <= m; j++) {
            while (l < r && (g[q[l + 1]] - g[q[l]]) <= (q[l + 1] - q[l]) * t[j])l++;
            f[i][j] = min(f[i - 1][j], g[q[l]] + t[j] * (j - q[l]) - s[j]);
            while (l < r && (g[q[r]] - g[q[r - 1]]) * (j - q[r]) >= (g[j] - g[q[r]]) * (q[r] - q[r - 1]))r--;
            q[++r] = j;
        }
    }
    printf("%lld\n", f[p][m]);
    return 0;
}
发布了360 篇原创文章 · 获赞 28 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_45323960/article/details/105049687