• CF331B Cats Transport[斜率优化dp+贪心]


    luogu翻译

    一些山距离起点有距离且不同,m只猫要到不同的山上去玩ti时间,有p个铲屎官人要去把所有猫接走,步行速度为1单位每秒,从1走到N座山不停下,必须在猫玩完后才可以把他带走。可以提前出发。问所有猫最少等待时间之和。


    这题一开始有个模糊想法就是$f[i][j]$表示前i个人接j只猫,但是猫是乱序的,必须找一种方法顺序的dp。想到排序。但是排时间抑或是距离都不对,要考虑优先接哪个。然后瞎想到每只猫可以让人在$T_i-dis_i$时刻从起点出发正好接到不用等,那接一堆猫等待时间取决于要求出发最迟的那只猫。把每只猫正好接到要求的出发时间做一下从小到大排个序,一个人接某批猫,每只猫的等待时间就是最大出发时间减去接这只猫的出发时间。然后考虑在这上面dp。然而选的猫不一定连续。可以证明(怎么证?我也不会),只有每个人接这里面连续的一批猫才有可能产生最优解。可以意会一下,我原来连续的一段,中间有一个给下一个人带走,等待时间更长,给上一个人带走,差不多、大概、应当也不优。实在不行可以打表看一下,比较其他划分有没有比连续划分优的。反正我是根据类似经历感觉出来的。

    然后方程很好写,区间划分。sum是等待时间前缀和,方便转移。a是等待时间,注意在排完序后就单调了。

    $f[i][j]=min{f[i-1][k]+(j-k)*a[j]-(sum[j]-sum[k])} $       $   i<=j<=n $     $ i-1<=k<j$

    然后拆开写斜截式,搞搞就斜率优化维护下凸壳,又斜率单调增,所以上述$O(pm^2)$化为$O(pm)$

    $f[i-1][k]+sum[k]=a[j]*k+j*a[j]+f[i][j]+sum[j]$


    记下错误:

    初始化又错!初始化又错!初始化又错!LINE23.真的不能再犯了。。。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
     5 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
     6 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
     7 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
     8 template<typename T>inline T read(T&x){
     9     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    10     while(isdigit(c))x=x*10+c-'0',c=getchar();return f?x=-x:x;
    11 }
    12 const int N=100000+7;
    13 ll f[103][N],d[N],a[N],sum[N],hi,ti;
    14 int q[N];
    15 int n,m,p,l,r;
    16 inline ll y(int k,int i){return f[i-1][k]+sum[k];}
    17 
    18 int main(){//freopen("test.in","r",stdin);//freopen("tmp.out","w",stdout);
    19     read(n),read(m),read(p);if(p>=m)return printf("0
    "),0;
    20     for(register int i=2;i<=n;++i)d[i]=read(d[i])+d[i-1];
    21     for(register int i=1;i<=m;++i)read(hi),read(ti),a[i]=ti-d[hi];
    22     sort(a+1,a+m+1);
    23     for(register int i=1;i<=m;++i)sum[i]=a[i]+sum[i-1],f[1][i]=i*1ll*a[i]-sum[i];//MISTAKES! 
    24     for(register int i=2;i<=p;++i){
    25         q[l=r=1]=i-1;
    26         for(register int j=i;j<=m;++j){
    27             while(l<r&&y(q[l+1],i)-y(q[l],i)<=(q[l+1]-q[l])*1ll*a[j])++l;
    28             f[i][j]=f[i-1][q[l]]+(j-q[l])*1ll*a[j]-sum[j]+sum[q[l]];
    29             while(l<r&&(y(q[r],i)-y(q[r-1],i))*(j-q[r])>=(y(j,i)-y(q[r],i))*(q[r]-q[r-1]))--r;
    30             q[++r]=j;
    31         }
    32     }
    33     printf("%I64d
    ",f[p][m]);
    34     return 0;
    35 }
  • 相关阅读:
    linux每日命令(31):tar命令
    Django——model基础
    Django——模板层(template)(模板语法、自定义模板过滤器及标签、模板继承)
    Django
    linux每日命令(30):Linux 用户及用户组相关文件、命令详解
    linux每日命令(29):chown命令
    20170430深圳Meetup
    静态库嵌套引用问题
    JD-Store购物网站复盘——20170312
    20170305Meetup Git、heroku drop db
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10462237.html
Copyright © 2020-2023  润新知