分析
这道题首先的问题是数据存放,由于要循环访问,可能会想到循环队列。这里我把数组扩大三倍,首尾相接,于是可以循环访问。但是由于程序每次都需要累加,当数据量大的时候会超时,导致最后一个测试点无法通过。
#include<iostream>
#include<algorithm>
using namespace std;
int d[300005];
int main() {
int n; scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int t; scanf("%d",&t);
d[i] = d[n + i] = d[2 * n + i] = t;
}
int m; scanf("%d", &m);
while (m--) {
int a, b;
scanf("%d%d", &a, &b);
if (a > b) swap(a, b);
int i = n + a, diff = b - a, sum1 = 0, sum2 = 0;
for (int k = 0; k < diff; k++) {
sum1 += d[i + k];
}
for (int k = 0; k < n - diff; k++) {
sum2 += d[i - 1 - k];
}
printf("%d\n", sum1 < sum2 ? sum1 : sum2);
}
return 0;
}
于是想到一种降低时间复杂度的方法:如果可以找到一个界限,该界限内的区间都是按某一个方向。按照题目的设定,是存在这样的界限的。可是这样的程序依旧超时。
柳神思路
由于相反方向的距离相加为总距离,因此只需要求在数组范围内的距离即可。也可以像1042 Shuffling Machine一样在输入时求和,节省时间。
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;
int main() {
int n;
scanf("%d", &n);
vector<int> dis(n + 1);
int sum = 0, left, right, cnt;
for (int i = 1; i <= n; i++) {
int temp;
scanf("%d", &temp);
sum += temp;
dis[i] = sum;
}
scanf("%d", &cnt);
for (int i = 0; i < cnt; i++) {
scanf("%d %d", &left, &right);
if (left > right) swap(left, right);
int temp = dis[right - 1] - dis[left - 1];
printf("%d\n", min(temp, sum - temp));
}
return 0;
}