hdu 5261 蜀道难(deque 双端队列)

度度熊最近去四川游玩了一趟,在西南边,它发现了一个神奇的地方,那里有数不清的山,山脚的路组成了一个完美的圆,而山均匀的坐落在这个圆上。“此乃造物者之无尽藏也”,它大发诗情的感慨道。

山高皆不一,度度熊现在很想知道,距离最远的两座山顶是哪两座山。由于山顶不能直接到达,从一座山顶到另一座山顶的唯一方法是,先下山,沿着山脚的圆走到另一个山脚,再上山。当然,在山脚可以选择任意方向行走。
 

Input
第一行一个整数T,表示T组数据。

每组数据的第一行包含两个整数$N (2 \leq N \leq 100 000)$ 和$R (1 \leq R \leq 10^9)$,表示山的个数和圆的半径。注意这里圆的半径不是R,而是NR/2PI (PI=3.1415926…) 。

接着的一行包括N个整数$H_i (1 \leq H_i <= 10^9)$,表示山峰的高度。
 

Output
对第i组数据,输出

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

http://acm.hdu.edu.cn/showproblem.php?pid=5261

#include<iostream>  
#include<algorithm>  
#include<string>  
#include<map>  
#include<set>  
#include<cmath>  
#include<vector>
#include<queue>
#include<deque>
#include<string.h>  
#include<stdlib.h>  
#include<cstdio> 
#define ll long long 
using namespace std; 
int x[200002];
int n,r,dis,st,ed;
deque<pair<int,ll> > q;
void pushh(int i){
    while(!q.empty()&&q.back().second+dis<x[i]) 
        q.pop_back();
    q.push_back(make_pair(i,x[i]-dis));
}
int main(){
    int t;
    scanf("%d",&t);
    int Case=1;
    while(t--){
        q.clear();
        scanf("%d%d", &n, &r);
        for(int i=0;i<n;++i)
            scanf("%d", &x[i]),x[i+n]=x[i];
        dis=0;
        ll s=0;
        for(int i=0;i<n/2;++i,dis+=r)
            pushh(i);
        for(int i=n/2;i<n+n/2;++i,dis+=r){
            int a=q.front().first%n;
            int b=i%n;
            if(a>b)
                swap(a,b);
            ll ss=q.front().second+x[i]+dis;
            if(ss>s){
                s=ss;
                st=a;
                ed=b;
            } 
            else if(ss==s&&(a<st||(a==st&&b<ed))){
                st=a;
                ed=b;
            }
            if(!q.empty()&&q.front().first<=i-n/2) //只扫到前n/2为止 
                q.pop_front();
            pushh(i);
        }
        printf("Case #%d:\n",Case++);  
        printf("%d %d\n",st+1,ed+1);  
    } 
    return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值