环路运输

在一条环形公路旁均匀地分布着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)。求在哪两座仓库之间运送货物需要的代价最大。
输入
第一行一个整数N,第二行N个整数A1~AN。
1≤N≤10^6,1<=Ai<=10^7
输出
一个整数,表示最大代价。
样例输入
5
1 8 6 2 5
样例输出
15
//在第2个仓库到第5个仓库之间进行运输货物

Sol:

ans=a[i]+i+a[j]-j,于是针对a[j]-j这个属性维护一个单调队列 ,另此题是一个环,于是破环为链就好了。

//ans=a[i]+i+a[j]-j,于是针对a[j]-j这个属性维护一个单调队列 
#include <bits/stdc++.h>
using namespace std;
int in(){
    int ans=0; char c=getchar();
    while (c<48||c>57) c=getchar();
    while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
    return ans;
}
int n,a[2000001],q[2000001],head,tail,ans;
int max(int a,int b){return (a>b)?a:b;}
int main(){
    n=in(); head=1;
    for (int i=1;i<=n;i++) a[i]=a[i+n]=in();
    for (int i=1;i<(n<<1);i++)
	{
	//	cout<<"i is   "<<i<<endl;
        while (head<=tail&&i-q[head]>(n>>1)) 
		//如果当前点与队列中头结点距离超过n/2 
		     head++;
	//	cout<<"before the queue is  "<<endl;
	//	for (int j=head;j<=tail;j++)
	//	     cout<<q[j]<<"   "<<a[q[j]]-q[j]<<endl;
	//	cout<<endl;
	//	system("pause");
        ans=max(ans,a[i]+i+a[q[head]]-q[head]); //取最优值 
        while (head<=tail&&a[i]-i>=a[q[tail]]-q[tail]) 
		//维护一个单调下降队列,队首值是最大的 
		       tail--;
        q[++tail]=i;
   	//	cout<<"after the queue is  "<<endl;
	//	for (int j=head;j<=tail;j++)
	//	     cout<<q[j]<<"   "<<a[q[j]]-q[j]<<endl;
	//	cout<<endl;

    }
    return !printf("%d",ans);
}

  

原文地址:https://www.cnblogs.com/cutemush/p/13628077.html