• 洛谷Cats Transport


    题意翻译

    Zxr960115 是一个大农场主。

    他养了 mm 只可爱的猫子,雇佣了 pp 个铲屎官。这里有一条又直又长的道路穿过了农场,有 nn 个山丘坐落在道路周围,编号自左往右从 11 到 nn。山丘 ii 与山丘 i-1i1 的距离是 D_iDi 米。铲屎官们住在 11 号山丘。

    一天,猫子们外出玩耍。猫子 ii 去山丘 H_iHi 游玩,在 T_iTi 时间结束他的游玩,然后在山丘 H_iHi 傻等铲屎官。铲屎官们必须把所有的猫子带上。每个铲屎官直接从 H_1H1 走到 H_nHn,中间不停下,可以认为不花费时间的把游玩结束的猫子带上。每个铲屎官的速度为一米每单位时间,并且足够强壮来带上任意数量的猫子。

    举个栗子,假装我们有两个山丘( D_2=1D2=1 ),有一只猫子,他想去山丘 22 玩到时间 33。然后铲屎官如果在时间 22 或者时间 33 从 11 号山丘出发,他就能抱走猫子。如果他在时间 11 出发那么就不行(猫子还在玩耍)。如果铲屎官在时间 22 出发,猫子就不用等他(Delta T=0ΔT=0)。如果他在时间 33 出发,猫子就要等他 11 个单位时间。

    你的任务是安排每个铲屎官出发的时间,最小化猫子们等待的时间之和。

    对于全部的数据,满足 2le nle10^52n105,1le mle10^51m105,1le ple1001p100,1le D_i<10^41Di<104,1le H_ile n1Hin,0le tle10^90t109。

    输入输出样例

    输入 #1
    4 6 2
    1 3 5
    1 0
    2 1
    4 9
    1 10
    2 10
    3 12
    
    输出 #1
    3

    _________________________________________________________

    每一只猫,最初可以接到的时间减去路程时间,就是管理员最早出发可以接到这只猫的时间。
    那么这样处理以后,就得到了接到每一只猫的最初时间。
    这样题目就变成了把m只猫分给p个管理员,让他们去接就是了。
    这样,首先将所有的猫的接他们的最初出发时间按大小排序。然后对这些猫进行分组并DP就可以了。
    f[i][j]=min(f[x][j-1]+t[i]*i-t[i]*x-smt[i]+smt[x])
    f[i][j]:前i只猫由j个人来借走
    由于出现t[i]*x,所以考虑斜率优化!

    在一本通评测网站,只能过部分,读入优化也用了,斜率也由出发给为了乘法。还是过不了。
    洛谷过了!
    _________________________________________________________

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int  maxn=1e5+10;
     5 ll dis[maxn],t[maxn],smt[maxn];
     6 ll n,m,p;
     7 ll f[maxn][105];
     8 ll q[maxn],l,r;
     9 inline ll y(ll a,ll j)
    10 {
    11     return f[a][j-1]+smt[a];
    12 }
    13 void readint(ll &x)
    14 {
    15     char c=getchar();
    16     ll f=1;
    17     for(;c>'9'||c<'0';c=getchar())if(c=='-')f=-1;
    18     x=0;
    19     for(;c<='9'&& c>='0';c=getchar())x=x*10+c-'0';
    20     x*=f;
    21 }
    22 int main()
    23 {
    24     readint(n);readint(m);readint(p);
    25 //    scanf("%lld%lld%lld",&n,&m,&p);
    26     for(ll i=2;i<=n;++i)
    27     {
    28 //        scanf("%lld",dis+i);
    29         readint(dis[i]);
    30         dis[i]+=dis[i-1];
    31     }
    32     for(ll hh,tt,i=1;i<=m;++i)
    33     {
    34 //        scanf("%lld%lld",&hh,&tt);
    35         readint(hh);readint(tt);
    36         t[i]=(ll)tt-dis[hh];
    37     }
    38     sort(t+1,t+1+m);
    39     for(ll i=1;i<=m;++i)
    40         smt[i]=t[i]+smt[i-1];
    41     memset(f,0x3f,sizeof f);
    42     f[0][0]=0;
    43     for(ll j=1;j<=p;++j)
    44     {
    45         l=r=0;
    46         for(ll i=1;i<=m;++i)
    47         {
    48             while(l<r && (y(q[l+1],j)-y(q[l],j))<=t[i]*(q[l+1]-q[l]))++l;
    49             //getxl(q[l],q[l+1],j)<=t[i]
    50             f[i][j]=f[q[l]][j-1]+t[i]*i-t[i]*q[l]-smt[i]+smt[q[l]];
    51             while(l<r && (y(q[r],j)-y(q[r-1],j))*(i-q[r])>=(y(i,j)-y(q[r],j))*(q[r]-q[r-1]))--r;
    52             //getxl(q[r-1],q[r],j)>=getxl(q[r],i,j)
    53             q[++r]=i;
    54         }
    55     }
    56     printf("%lld",f[m][p]);
    57     return 0;
    58 }
    View Code


  • 相关阅读:
    将博客搬至CSDN
    【LeetCode & 剑指offer刷题】熟悉OJ平台3:OJ编程实例
    【LeetCode & 剑指offer刷题】熟悉OJ平台2:如何处理输入问题
    【LeetCode & 剑指offer刷题】熟悉OJ平台1:OJ术语
    【LeetCode & 剑指offer刷题】发散思维题9:Shuffle an Array
    【LeetCode & 剑指offer刷题】发散思维题8:Roman to Integer
    【LeetCode & 剑指offer刷题】发散思维题7:Fizz Buzz
    【LeetCode & 剑指offer刷题】发散思维题6:231. Power of Two(系列)
    【LeetCode & 剑指offer刷题】发散思维题5:65 不用加减乘除做加法
    【LeetCode & 剑指offer刷题】发散思维题4:64 求1+2+…+n
  • 原文地址:https://www.cnblogs.com/gryzy/p/14419110.html
Copyright © 2020-2023  润新知