题意

Zxr960115 is owner of a large farm. He feeds m cute cats and employs p feeders. There's a straight road across the farm and n hills along the road, numbered from 1 to n from left to right. The distance between hill i and (i - 1) is di meters. The feeders live in hill 1.

One day, the cats went out to play. Cat i went on a trip to hill hi, finished its trip at time ti, and then waited at hill hi for a feeder. The feeders must take all the cats. Each feeder goes straightly from hill 1 to n without waiting at a hill and takes all the waiting cats at each hill away. Feeders walk at a speed of 1 meter per unit time and are strong enough to take as many cats as they want.

For example, suppose we have two hills (d2 = 1) and one cat that finished its trip at time 3 at hill 2 (h1 = 2). Then if the feeder leaves hill 1 at time 2 or at time 3, he can take this cat, but if he leaves hill 1 at time 1 he can't take it. If the feeder leaves hill 1 at time 2, the cat waits him for 0 time units, if the feeder leaves hill 1 at time 3, the cat waits him for 1 time units.

Your task is to schedule the time leaving from hill 1 for each feeder so that the sum of the waiting time of all cats is minimized.

\(2 ≤ n ≤ 10^5, 1 ≤ m ≤ 10^5, 1 ≤ p ≤ 100\)

分析

参照ww3113306的博客。

首先我们观察到山与距离其实是没有什么用的,因为对于任意一只猫,我们都可以直接算出如果有一个人要恰好接走它,需要在哪一时刻出发,我们设第i只猫对应的这个时刻为\(t_{i}\).

注意这个\(t_{i}\)是我自己新定义的,跟题目中的没有关系,下面所写的t都是我现在所定义的t,而跟原题面中的t没有任何关系。

然后我们对t数组排个序,于是题意转化为了有m只猫,每只猫有一个权值\(t_{i}\),如果出发时间大于等于\(t_{i}\) ,则可以接到第i只猫。设出发时间为x,则接到第i只猫时,这只猫会等待\(x - t_{i}\)的时间。现在有p个人,要求为每个人指定一个时间使得所有猫的等待时间之和最小。

然后我们继续转化题意。

观察到每个人相当于会选择一只猫i,然后选择在\(t_{i}\)时刻出发,恰好接走这只猫,顺便可以接走其他可以被接走的猫。

为什么是每个人都必须选一只猫呢?

观察到如果一个人出发,没有任何一只猫是恰好被接到的,所有猫都是等了一会再被接走的,那么这个人为什么不早出发一点,恰好接走一些猫呢?这样不仅可以接走和上一种方案相同的猫,还可以减小等待时间。

于是现在题意转化为了有m只猫,每只猫有一个权值\(t_{i}\)。如果第x个人选择了第i只猫,上一个出发的人选了第j只猫,则这个人可以接走[j + 1, i]中的所有猫,并且代价为\(\sum_{k = j + 1}^{i}{t_{i} - t_{k}}\)。现在有p个人,要求为每个人指定一只猫使得所有猫的等待时间之和最小。

先化一下式子:(其中s[i]表示\(\sum_{k = 1}^{i}{t[k]}\))
\[
\sum_{k = j + 1}^{i}{t_{i} - t_{k}} \\
= \sum_{k = j + 1}^{i}{t_{i}} - \sum_{k = j + 1}^{i}{t_{k}} \\
= (i - j) t_{i} - (s[i] - s[j])=(i−j)t
\]
于是我们设f[i][j]表示DP到第i个人,这个人选择了第j只猫的最小代价。

然后暴力枚举i,j,转移的时候再暴力枚举前一个人选了哪只猫即可。

但是这样的复杂度是\(pm^2\)的,观察到我们优化到\(pm\)就可以过了,又注意到式子中有一个跟i相关的量和一个跟j相关的量的乘积,我们考虑一下斜率优化。

我们先化一波式子。
\[
f[i][j] = f[i - 1][k] + (j - k) t_{j} - (s[j] - s[k])
\]
然后设\(x>y\),且\(x\)比\(y\)优,则
\[
\frac{f[i-1][x]+s[x]-f[i-1][y]-s[y]}{x-y}<t[i]
\]
小于单调增,下凸包+单调队列。

时间复杂度\(O(pm)\)

代码

我还是第一次做到多次斜率优化,并且弹出的和入队的比较内容不一样,感觉理解又深了一层。CF上面的题的质量很高,具有创新性,可以尝试。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<ctime>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
    rg T data=0;
    rg int w=1;
    rg char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data*w;
}
template<class T>T read(T&x)
{
    return x=read<T>();
}
using namespace std;
typedef long long ll;

co int M=1e5+1,P=101;
ll d[M],t[M],s[M];
ll f[P][M];

ll Up(int i,int x,int y) // edit 1: use ancient information,push anciently
{
    return f[i-1][x]+s[x]-f[i-1][y]-s[y];
}

ll Down(int x,int y)
{
    return x-y;
}

ll Cal(int i,int j,int k)
{
    return f[i-1][k]+(j-k)*t[j]-s[j]+s[k];
}

int q[M];

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    int n=read<int>(),m=read<int>(),p=read<int>();
    for(int i=2;i<=n;++i)
        d[i]=d[i-1]+read<int>();
    for(int i=1;i<=m;++i)
    {
        int h=read<int>();
        t[i]=read<int>()-d[h];
    }
    sort(t+1,t+m+1);
    for(int i=1;i<=m;++i)
        s[i]=s[i-1]+t[i];

    for(int j=1;j<=m;++j)
        f[1][j]=j*t[j]-s[j];
    for(int i=2;i<=p;++i)
    {
        int head=0,tail=0;
        q[tail++]=0;
        for(int j=1;j<=m;++j)
        {
            while(head+1<tail&&Up(i,q[head+1],q[head])<=t[j]*Down(q[head+1],q[head]))
                ++head;
            f[i][j]=Cal(i,j,q[head]);
            while(head+1<tail&&Up(i,j,q[tail-1])*Down(q[tail-1],q[tail-2])<=Up(i,q[tail-1],q[tail-2])*Down(j,q[tail-1]))
                --tail;
            q[tail++]=j; // edit 2:push j
        }
    }
    printf("%I64d\n",f[p][m]);
    return 0;
}

CF311B Cats Transport的更多相关文章

  1. CF311B Cats Transport 斜率优化DP

    题面:CF311B Cats Transport 题解: 首先我们观察到山与距离其实是没有什么用的,因为对于任意一只猫,我们都可以直接算出如果有一个人要恰好接走它,需要在哪一时刻出发,我们设第i只猫对 ...

  2. 题解 CF311B Cats Transport

    前置芝士:斜率优化  剥下这道题的外壳,让它变为一道裸的斜率优化. 很容易想到状态,但复杂度显然过不去,也没有单调性,只能自己创造. 令 $$c[i] = t - sum[i],sum[i] = \s ...

  3. CF311B Cats Transport(斜率优化)

    题目描述 Zxr960115 是一个大农场主.他养了m只可爱的猫子,雇佣了p个铲屎官.这里有一条又直又长的道路穿过了农场,有n个山丘坐落在道路周围,编号自左往右从1到n.山丘i与山丘i-1的距离是Di ...

  4. $CF311B\ Cats\ Transport$ 斜率优化

    AcWing Description Sol 设f[i][j]表示前i个饲养员接走前j只猫咪的最小等待时间. 要接到j猫咪,饲养员的最早出发时间是可求的,设为d: $ d[j]=Tj-\sum_{k= ...

  5. CF-311B Cats Transport(斜率优化DP)

    题目链接 题目描述 小S是农场主,他养了 \(M\)只猫,雇了 \(P\) 位饲养员. 农场中有一条笔直的路,路边有 \(N\) 座山,从 \(1\) 到 \(N\)编号. 第 \(i\) 座山与第 ...

  6. 一本通1609【例 4】Cats Transport

    1609:[例 4]Cats Transport 时间限制: 1000 ms         内存限制: 524288 KB sol:非常偷懒的截图了事 注意:只能猫等人,不能人等猫 对于每只猫,我们 ...

  7. Codeforces 311B Cats Transport 斜率优化dp

    Cats Transport 出发时间居然能是负的,我服了... 卡了我十几次, 我一直以为斜率优化写搓了. 我们能得出dp方程式 dp[ i ][ j ] = min(dp[ k ][ j - 1 ...

  8. 【题解】Cats Transport (斜率优化+单调队列)

    [题解]Cats Transport (斜率优化+单调队列) # When Who Problem Lang Verdict Time Memory 55331572 Jun/09/2019 19:1 ...

  9. Cats transport(codeforces311B)(斜率优化)

    \(Cats Transport\) 感觉这道题题面不好讲,就自翻了一个新的,希望有助于大家理解其思路: 大致题意: \(wch\) 的家里有 \(N\) 座山(山呈直线分布,第 \(i-1\) 座山 ...

随机推荐

  1. GIT使用—一些概念

    (1)Git版本库(repository) 一个简单的数据库,包括所有用来维护与管理项目的修订版本和历史的信息. Git维护两个主要的数据结构: 对象库(object store)-在复制操作时能进行 ...

  2. APP测试的要点

    APP测试要点 功能性 UI界面 安装与卸载 升级 登录测试 离线测试 安全性测试 兼容性(操作系统,屏幕尺寸,分辨率,厂家) 消息推送 前后台切换 网络环境(wifi/2G/3G/4G/无网) 异常 ...

  3. Mysql 慢查询日志配置

    查询日志 1.主配置文件下对添加参数.重启生效. vim /etc/my.cnf 注:主要用于查看开发程序执行时间. 注:log_slow_queries = /tmp/mysql.slow    # ...

  4. uiautomator--图像处理

    一.图像处理在自动化中使用场景 1)效果类截图  图像处理技术在自动化的场景中很容易使用到.自动化不是万能的,有时候效果类的是无法进行验证的,但是效果类一般会有图像显示,我们可以通过截图对比实现. 2 ...

  5. Git服务器的Gitosis安装配置及gitignore的使用方法

    Git服务器Gitosis安装设置 1.安装 openssh服务器 sudo apt-get install openssh-server openssh-client 2.创建个人公钥和私钥 在默认 ...

  6. Mysql 语句单表查询

    一基本查询 -- 创建商品表 CREATE TABLE products( pid INT PRIMARY KEY AUTO_INCREMENT, pname VARCHAR(20), price D ...

  7. ubuntu 16.04 vscode + php debug

    1.vscode 安装PHP Debug扩展: 2.php环境配置: 1.安装xdebug扩展: sudo apt-get install php-xdebug 2.找到扩展的路径: chq@chq- ...

  8. PermutationsUnique,求全排列,去重

    问题描述:给定一个数组,数组里面有重复元素,求全排列. 算法分析:和上一道题一样,只不过要去重. import java.util.ArrayList; import java.util.HashSe ...

  9. JNIjw01

    1.VC6(CPP)的DLL代码: #include<stdio.h> #include "jniZ_JNIjw01.h" JNIEXPORT void JNICALL ...

  10. 通过使用Netty实现RPC

    目标:通过使用Netty框架实现RPC(远程过程调用协议),技术储备为以后实现分布式服务框架做技术储备.在这里实现自定义协议主要实现远程方法调用. 技术分析: 1.通过Java的反射技术我们可以获取对 ...