HDU5261 蜀道难【单调队列】

题意:中文题,他给的半径实际上就是两点之间的距离,然后要求找出两个点的权值加上之间的距离最大。

a数组表示每个点的权值,设两个点分别是i,j,所以答案就是a[i]-i*r+a[j]+j*r,对于一个j应该要找到满足要求最大的a[i]-i*r,所以就用单调队列了,还要注意就是单调队列里相等的话就直接加到队尾,优先取编号小的。

#include
#include
#include
using namespace std;
const int MAXN=100010;
typedef long long ll;
typedef pair Point;
int q[MAXN<<1];
ll a[MAXN<<1];
int main()
{
	int t,n,i,flag=1;
	ll r;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%lld",&n,&r);
		for(i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
			a[i+n]=a[i];
		}
		int front=0,rear=-1;
		Point ans;
		ll aans=0;
		q[++rear]=1;
		for(i=2;i<=2*n;i++)
		{
			while(front<=rear&&(i-q[front])>n/2)
				front++;
			if(front<=rear&&a[i]+a[q[front]]-q[front]*r+i*r>aans)
			{
				aans=a[i]+a[q[front]]-q[front]*r+i*r;
				ans.first=min(q[front],i);
				ans.second=max(q[front],i);
				if(ans.first>n)
					ans.first-=n;
				if(ans.second>n)
					ans.second-=n;
				if(ans.first>ans.second)
					swap(ans.first,ans.second);
			}
			else if(front<=rear&&a[i]+a[q[front]]-q[front]*r+i*r==aans)
			{
				Point temp;
				temp.first=min(q[front],i);
				temp.second=max(q[front],i);
				if(temp.first>n)
					temp.first-=n;
				if(temp.second>n)
					temp.second-=n;
				if(temp.first>temp.second)
					swap(temp.first,temp.second);
				if(temp


你可能感兴趣的:(乱搞)