蜀道难
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 375 Accepted Submission(s): 118
Problem Description
度度熊最近去四川游玩了一趟,在西南边,它发现了一个神奇的地方,那里有数不清的山,山脚的路组成了一个完美的圆,而山均匀的坐落在这个圆上。“此乃造物者之无尽藏也”,它大发诗情的感慨道。
山高皆不一,度度熊现在很想知道,距离最远的两座山顶是哪两座山。由于山顶不能直接到达,从一座山顶到另一座山顶的唯一方法是,先下山,沿着山脚的圆走到另一个山脚,再上山。当然,在山脚可以选择任意方向行走。
山高皆不一,度度熊现在很想知道,距离最远的两座山顶是哪两座山。由于山顶不能直接到达,从一座山顶到另一座山顶的唯一方法是,先下山,沿着山脚的圆走到另一个山脚,再上山。当然,在山脚可以选择任意方向行走。
Input
第一行一个整数T,表示T组数据。
每组数据的第一行包含两个整数 N(2≤N≤100000)
和
R(1≤R≤10
9
)
,表示山的个数和圆的半径。注意这里圆的半径不是R,而是NR/2PI (PI=3.1415926…) 。
接着的一行包括N个整数 H
i
(1≤H
i
<=10
9
)
,表示山峰的高度。
每组数据的第一行包含两个整数 N(2≤N≤100000)
接着的一行包括N个整数 H
Output
对第i组数据,输出
Case #i:
然后输出两座山峰的ID (从1开始),如果有多组答案,输出字典序最小的一对。
Case #i:
然后输出两座山峰的ID (从1开始),如果有多组答案,输出字典序最小的一对。
Sample Input
2 3 1 1 1 1 5 2 1 10 1 10 10
Sample Output
Case #1: 1 2 Case #2: 2 4
思路:相当于求h[j]+h[i]+(j-i)*r (i<j,j-i<=n/2),由于是圆圈的我们把数组扩增成原来的两倍,然后我们用一个长度为n/2的队列维护,队列头部存放离当前点距离最远的点,并用另一个队列存放最远点的 高度-位置*半径, 队列头部最远且下标最小,后面的距离点未必比头部小但下标比较大
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<string>
#include<cmath>
#include<iostream>
#include<deque>
using namespace std;
#define LL long long
#define ULL unsigned long long
const int maxn = 100005;
int num[maxn*2];
deque<int> Q;
deque<LL> QS;
int n,r,ti=1,t;
int main(void){
scanf("%d",&t);
LL ans;
int ax,ay;
int tx,ty;
while(t--){
ans = 0;
printf("Case #%d:\n",ti++);
scanf("%d%d",&n,&r);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]),num[i+n]=num[i];
while(!Q.empty()) Q.pop_back(),QS.pop_back();
for(int i=1;i<=2*n;i++){
while(!Q.empty()&&(i-Q.front())*2>n) //使长度保持n/2
Q.pop_front(),QS.pop_front();
if(!Q.empty()&&(i-Q.front())*2<=n&&1LL*num[i]+1LL*r*i+QS.front()>=ans){
tx = Q.front();
ty = i;
if(tx>n) tx-=n;
if(ty>n) ty-=n;
if(tx>ty) tx=tx^ty,ty=tx^ty,tx=tx^ty;
if(1LL*num[i]+1LL*r*i+QS.front()>ans)
ax = tx,ay=ty,ans = 1LL*num[i]+1LL*r*i+QS.front();
else if(tx<ax||(tx==ax&&ty<ay)) ax=tx,ay=ty;
}
LL now = num[i]-1LL*r*i;
while(!Q.empty()&&now>QS.back()) //使末尾肯定是下标最大的,除去比当前点下标小且距离没当前点远的点
Q.pop_back(),QS.pop_back();
Q.push_back(i);
QS.push_back(now);
}
printf("%d %d\n",ax,ay);
}
return 0;
}