タスクは非常に単純です。単純なサイクルを形成する高速道路のN個の出口がある場合、出口のペア間の最短距離を伝える必要があります。
入力仕様:
各入力ファイルには1つのテストケースが含まれています。いずれの場合も、最初の行には整数N([3,10_ 5]内)が含まれ、その後にN整数の距離D 1 D 2⋯D Nが続きます。ここで、D iはi番目と(i + 1)番目の出口の間の距離であり、D NはN番目と1番目の出口の間です。行内のすべての数値はスペースで区切られています。2番目の行は正の整数M(≤10_4)を示し、M行が続き、出口に1からNまでの番号が付けられている場合、それぞれに出口番号のペアが含まれます。総往復距離がは10 7以下です。
出力仕様:
各テストケースについて、結果をM行で出力します。各行には、対応する特定の出口のペア間の最短距離が含まれています。
入力例:
5 1 2 4 14 9
3
1 3
2 5
4 1
出力例:
3
10
7
//この質問の意味は、円にn個の点があることです。任意の2点間の最小距離を見つけます。なぜ最小距離があるのですか?リング上ではa-> bなので、時計回りまたは反時計回りになり、移動距離が異なる場合があります。計算方法は比較的簡単です。距離を時計回り(反時計回り)に計算し、円の円周の半分と比較できます。円周の半分未満の場合、距離は希望の距離です。それ以外の場合は、円周マイナスです。距離。これは最も単純なシミュレーションですが、2つのポイントを取得するたびに1つずつ距離を合計すると、問題のデータがn max 1e5、m max 1e4であることに注意してください。ピットを踏んだ)。解決策は、Diを読み取るときに(i + 1)番目のポイントから最初のポイント(No. 1)までの距離dis [i + 1]を見つけることです。a-> bからの距離を見つけるときは、disを計算するだけです。 [b] -dis [a]で十分です。O(1)の複雑さで、タイムアウトはありません。以下に2種類のコードを示します。
法一:结果超时
#include<cstdio>
#include<algorithm>
using namespace std;
int a[100005];
int main() {
int n, sum = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum += a[i]; //求出圆的周长
}
int m, k;
k = sum / 2;
scanf("%d", &m);
while (m--) {
int x, y;
scanf("%d%d", &x, &y);
if (x > y) //默认是(x, y),所以当读入的x > y时,就交换x, y
swap(x, y); //初用C++,原来algorithm头文件里面有swap函数,就不用自己写了
int sum0 = 0; //sum0是x -> y的距离,初始为0
for (int i = x; i < y; i++)
sum0 += a[i];
printf("%d\n", sum0 < k ? sum0 : sum - sum0);
}
return 0;
}
//法二:AC了
#include<cstdio>
#include<algorithm>
using namespace std;
int a[100005], dis[100005]; //dis记录每个点到初始点(1号)的距离
int main() {
int n, sum = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum += a[i];
dis[i + 1] = sum; //因为是记录到第一个点的距离,就从第二个点开始,所以下标为 i + 1
}
int m, k;
k = sum / 2;
scanf("%d", &m);
while (m--) {
int x, y;
scanf("%d%d", &x, &y);
if (x > y)
swap(x, y)
int sum0 = dis[y] - dis[x]; //直接求出两点之间的距离
printf("%d\n", sum0 < k ? sum0 : sum - sum0);
}
return 0;
}
//何日も経って、Fa 2の考え方が前置和だと気づきました!!!