NYOJ 873 环之最大和

题目意思很简单  就是让你从n个数字中选取m个连续的数字使和最大  就是这样没错  因为是环状的 所以可以从末尾连到最开始 

PS: 如果你觉得写得一定没有错 但还是wa   你可能忽略了 long long 没错 恭喜你!!!(还要注意最后 MOD   n)

方法一 :  可以用前缀和 遍历一遍得到最大值和边界问题 





#include 
#include 
#include 
using namespace std;
const int maxn = 3000;
int main()
{
	int n, m, arr[maxn];
	long long pres[maxn];
	while (cin >> n >> m) {
		memset(pres , 0, sizeof(pres));
		for (int i = 1; i <= n; i ++) {
			cin >> arr[i];
			pres[i] = pres[i - 1] + arr[i];
		}
		for (int i = n + 1; i <= n + m; i ++) {
			arr[i] = arr[i - n];
			pres[i] = pres[i - 1] + arr[i];
		}
//		for (int i = 1; i <= n + m - 1; i ++) {
//			cout << arr[i] << " ";
//		}cout << endl;
//		for(int i = 1; i <= n + m - 1; i ++) {
//			cout << pres[i] << " ";
//		}
		int head , tail;
		long long ans = -999999;
		for (int i = m; i <= n + m; i ++) {
			if(pres[i] - pres[i - m ] > ans) {
				ans = pres[i] - pres[i - m ];
				head = i - m + 1;tail = i;
			}
		}
		if(head > n)head %= n;
		if(tail > n)tail %= n;
		cout << ans << " " << head << " " << tail << endl;
	}	
} 


方法二 是这样的  可以用尺取法  维护两个伪指针 和 中间变量来得到最大值  这样的好处在于 如果数组特别特别大   前缀和无法保存的时候  而且也比前缀和的方法更快





#include 
using namespace std;
const int maxn = 3000;
int main()
{
	int n, m, arr[3000];
	while (cin >> n >> m) {
		for (int i = 1 ;i <= n; i ++) {
			cin >> arr[i];
		}
		for (int i = n + 1; i <= n + m - 1; i ++) {
			arr[i] = arr[i - n];
		}
		int head = 1, tail = m;
		long long ans = -999999;
		long long temp = 0;
		for (int i = 1; i <= m; i ++) 
			temp += arr[i];
		ans = temp;
		int l = head;
		int r = tail;
		for (int i = 1; i < n; i ++) {
			temp += arr[++r];
			temp -= arr[l++];
			if( temp > ans ) {
				ans = temp;
				head = l;tail = r;
			}
		}
		if(head > n)head %= n;
		if(tail > n)tail %= n;
		cout << ans << " " << head << " " << tail << endl;
	}
}

没错我把两种方法对应反了  你以为我是不小心的??  笑话 我怎么可能没发现  我就是故意的  就是这么傲娇

你可能感兴趣的:(NYOJ 873 环之最大和)