1044 Shopping in Mars (25分)/二分法

自闭症网瘾萝莉.ら 提交于 2020-01-26 20:28:58

题目链接
一开始是用的简单模拟的方法做的,有两个测试点超时。于是把cin、cout改为了scanf、printf,可是仍然超时。主要是套了两层循环,时间复杂度为O(n^2)。
看了柳神代码,说要用二分法,于是我又想了想。可是还是每次把求sum的工作放在了函数里面,时间复杂度还是O(n^2)。然后才想到可以在输入时求从第一个数累计求和到当前的数,保存在数组中,这样方便于求子串的和。
用二分法的话这道题的时间复杂度应该是O(nlogn),快了很多。

AC代码

#include<iostream>
#include<cstring>
using namespace std;
int sum[100005], an[100005];
int min = 999999999;
int solve(int left, int right,int& m) {
	int mid,L=left;
	while (left < right) {
		mid = (left + right) / 2;
		if (sum[mid]-sum[L-1]>=m) right = mid;
		else left = mid + 1;
	}
	return left;
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		int t;scanf("%d", &t);
		sum[i] = sum[i - 1] + t;
	}
	int num = 0;
	for (int i = 1; i <= n; i++) {
		int j=solve(i, n, m);
		int temsum = sum[j] - sum[i - 1];
		if (temsum >= m) {  //由于二分法可能找到的只是一个假定的位置,即此题中j不存在时也会返回j=i;
			if (temsum > min) continue;
			if (temsum < min) {
				num = 0; min = temsum;
			}
			an[num++] = i; an[num++] = j;
		}
	}
	for (int i = 0; i < num; i += 2) {
		printf("%d-%d\n", an[i], an[i + 1]);
	}
	return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!