The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.
Input Specification:
Each input file contains one test case. For each case, the first line contains an integer N (in [3,10^5 ]), followed by N integer distances D1 D2 ⋯ DN , where Di is the distance between the i-th and the (i+1)-st exits, and DN
is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (≤10^4 ), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 10^7
.
Output Specification:
For each test case, print your results in M lines, each contains the shortest distance between the corresponding given pair of exits.
Sample Input:
5 1 2 4 14 9
3
1 3
2 5
4 1
Sample Output:
3
10
7
题意
给出有N个点的一个简单环和N个点之间的距离(最后一个数据为最后一个点到第一个点的距离),所有点编号为1~N。给出M个查询,求每个查询中一对点之间的最短距离。
思路
环上两个点之间的最短距离要么是从左端点直接到右端点,要么是从右端点到起始端点再走到左端点。所以我们用a[i]表示从1号到i+1号的距离。为了方便代码的书写,我们将编号映射到0~N-1。这样a[i]表示从0号到i号的距离(i = 1,…,N-1),所以a[0]为0号到自身的距离,当然就是0了,那么a[N]代表从N-1号到0号的距离。所以我们初始化a[0] = 0,然后边读入边依次计算从0号到第i号的距离。得到a数组后。对于M个查询,只需要再次将输入的两个点映射到0~N-1上,为了方便,总是取u为编号大的一个,v为编号小的一个。然后输出a[u] - a[v]和a[N] + a[v] - a[u]中小的一个。
代码
#include <cstdio>
#include <algorithm>
#define MAX_N 100000
using namespace std;
int a[MAX_N + 1];
int main() {
// 读取输入并计算a[i](i = 1,2...,N)
// a[i]代表从0号位置到i号位置的总距离
int N;
scanf("%d", &N);
a[0] = 0;
for(int i = 1, t; i <= N; i++){
scanf("%d", &t);
a[i] = a[i - 1] + t;
}
int M;
scanf("%d", &M);
for(int i = 0, u, v, t; i < M; i++){
scanf("%d %d", &u, &v);
// 交换编号(如果需要)使得u总是大于等于v,并将u、v映射到编号为0~N-1的空间
if(u > v){
t = u - 1;
u = v - 1;
v = t;
}else{
u--;
v--;
}
// 输出答案,最短距离要么是从v->u,要么是从u->N->v
printf("%d\n", min(a[v] - a[u], a[N] + a[u] - a[v]));
}
return 0;
}