• Cats Transport


    https://loj.ac/problem/10187

    题目描述

      一条路上有(N)座山,有(P)位饲养员在(1)号山,每只猫获取(H_i)号山玩到(T_i)时刻,求饲养员何时出发可以使所有猫的等待时间最短。

    思路

      我们考虑一下先直接求出恰好接到每只猫的时刻(a_i),那么我们贪心的考虑,每个管理员一定会带走按(a)排序后一段的猫,所以我们将猫分为批次,令(f[i][j])表示前(i)个饲养员带走(j)只猫的最少等待时间。那么

    [f[i][j]=min{f[i-1][k]-sum_{p=k}^ja[p]-a[k]} ]

      用前缀和优化后转移方程为

    [f[i][j]=min{f[i-1][k]+a[j]*(j-k)-s[j]+s[k]} ]

      我们把它化为有关(j)的一次函数

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

      这样我们就把就(f[i][j])的最小值转化为求截距的最小值,直接斜率优化即可。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll N=1e5+10;
    ll q[N],f[110][N],sumd[N],s[N],a[N],g[N];
    
    ll read()
    {
    	ll res=0,w=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    	return res*w;
    }
    
    int main()
    {
    	ll n,m,p;
    	n=read();m=read();p=read();
    	for(ll i=2;i<=n;i++)
    		sumd[i]=sumd[i-1]+read();
    	for(ll i=1;i<=m;i++)
    	{
    		ll h=read(),t=read();
    		a[i]=t-sumd[h];
    	}
    	sort(a+1,a+m+1);
    	for(ll i=1;i<=m;i++)
    		s[i]=s[i-1]+a[i];
    	memset(f,0x3f,sizeof(f));
    	f[0][0]=0;
    	ll l=0,r=0;
    	for(ll i=1;i<=p;i++)
    	{
    		for(ll j=1;j<=m;j++)
    			g[j]=f[i-1][j]+s[j];
    		l=0,r=0;q[0]=0;
    		for(ll j=1;j<=m;j++)
    		{
    			while(l<r&&g[q[l+1]]-g[q[l]]<a[j]*(q[l+1]-q[l]))l++;
    			f[i][j]=g[q[l]]+(j-q[l])*a[j]-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",f[p][m]);
    }
    
  • 相关阅读:
    查找算法——找到序列中第二大的数(修正版)
    排序算法——堆排序
    排序算法——选择排序
    排序算法——冒泡排序
    排序算法——快速排序
    2013年全国各大著名的IT公司薪资待遇大揭密 给出入职场的民工一点建议
    各大IT公司2012校园招聘笔试面试整理
    九大排序算法总结
    mysql之创建数据库,创建数据表
    各种排序算法汇总
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11853231.html
Copyright © 2020-2023  润新知