1046 Shortest Distance (20分)/简单模拟/降低时间复杂度

题目链接

分析

这道题首先的问题是数据存放,由于要循环访问,可能会想到循环队列。这里我把数组扩大三倍,首尾相接,于是可以循环访问。但是由于程序每次都需要累加,当数据量大的时候会超时,导致最后一个测试点无法通过。

#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;
}
发布了26 篇原创文章 · 获赞 5 · 访问量 418

猜你喜欢

转载自blog.csdn.net/weixin_43590232/article/details/104089867