环路运输

其实我觉得这道题很优秀的啊

题目描述

在一条环形公路旁均匀地分布着N座仓库,编号为1~N,编号为 i 的仓库与编号为 j 的仓库之间的距离定义为 dist(i,j)=min⁡(|i-j|,N-|i-j|),也就是逆时针或顺时针从 i 到 j 中较近的一种。每座仓库都存有货物,其中编号为 i 的仓库库存量为 A_i。在 i 和 j 两座仓库之间运送货物需要的代价为 A_i+A_j+dist(i,j)。求在哪两座仓库之间运送货物需要的代价最大。1≤N≤ 1 0 6 10^6 106,1<=Ai<= 1 0 7 10^7 107

分析

对于j<i<=n
i-j<=n/2----dist(i,j)=i-j;
i-j>n/2-----dist(i,j)=n-(i-j)=(n+j)-i (因为i-j>n/2,所以n+j-i<n/2); 设x为n+j(n<x<=2*n)相当于x-i
拆环成链,复制一遍放到最后
所以枚举每个点i表示它为出发点 走到它之前的点j,且dist(i,j)=i-j,的最大代价
也就是要找到一个点j使得
a[i]+a[j]+i-j=a[i]+i+a[j]-j最大,也就是要找一个最大的a[j]-j且i-j<n/2
单调队列维护

代码:

#include <bits/stdc++.h>
using namespace std;
int n,a[2000010],q[2000010];
int head=1,tail=0,ans=0;
int main()
{
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout); 
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	  scanf("%d",&a[i]);
	for (int i=1;i<=n;i++)
	  a[n+i]=a[i];
	for (int i=1;i<=2*n;i++)
	{
		while (head<=tail&&q[head]<i-n/2) head++;
		ans=max(ans,a[i]+a[q[head]]+i-q[head]);
		while (a[i]-i>=a[q[tail]]-q[tail]&&tail>=head) tail--;
		q[++tail]=i;
    }
    cout<<ans;
    return 0;
}
	  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值