• 洛谷 P5017 [NOIP2018 普及组] 摆渡车(斜率优化dp)


    传送门


    解题思路

    设dp[i]表示在第i秒发车时前面的人一共等候了多少分钟。
    朴素方程就是枚举 (j=0 o (i-m))

    [dp[i]=min(dp[i],dp[j]+i imes(cnt[i]-cnt[j])-(a[i]-a[j])) ]

    其中 (cnt[i]) 为前 i 秒的人数,(a[i]) 为前 i 秒的所有人的到达时间的和。
    把式子拆开并移项,就变成了 y=kx+b 的形式:

    [dp[j]+a[j]=i imes cnt[j]+dp[i]+a[i]-i imes cnt[i] ]

    其中 y=dp[j]+a[j],x=cnt[j],斜率就是 i。
    然后就套上斜率优化板子即可。
    注意最后答案是

    [ans=min_{i=t}^{t+m}{dp[i]} ]

    AC代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int maxn=4e6+105;
    int n,m,t[maxn],l=1,r=1,q[maxn],dp[maxn],cnt[maxn],a[maxn],ans=1e9;
    inline double cal(int l,int r){
    	return 1.0*(dp[r]+a[r]-dp[l]-a[l])/(cnt[r]==cnt[l]?1e-9:cnt[r]-cnt[l]);
    }
    int main(){
    	ios::sync_with_stdio(false);
    	cin>>n>>m;
    	for(int i=1;i<=n;i++) cin>>t[i],t[i]++;
    	sort(t+1,t+n+1);
    	int now=1;
    	for(int i=1;i<=t[n]+m;i++){
    		a[i]=a[i-1];
    		cnt[i]=cnt[i-1];
    		while(now<=n&&t[now]==i) now++,a[i]+=i,cnt[i]++;
    	}
    	q[1]=dp[0]=0;
    	for(int i=1;i<=t[n]+m;i++){
    		while(l<r&&cal(q[l],q[l+1])<=i) l++;
    		dp[i]=dp[q[l]]+i*(cnt[i]-cnt[q[l]])-(a[i]-a[q[l]]);
    		if(i<m) continue;
    		while(l<r&&cal(q[r-1],q[r])>=cal(q[r],i-m+1)) r--;
    		q[++r]=i-m+1;
    	}
    	for(int i=t[n];i<=t[n]+m;i++) ans=min(ans,dp[i]);
    	cout<<ans;
        return 0;
    }
    
  • 相关阅读:
    python计算机基础
    计算机基础知识
    ftok函数
    可重入函数与不可重入函数
    Redis学习资料整理
    小记6月18
    libxml2简单的生成、解析操作
    切换日志是否更新检查点?
    第五课 数据备份恢复实验
    第四课 Grid Control实验 GC Agent安装(第一台机器部署) 及卸载
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15256686.html
Copyright © 2020-2023  润新知