题目意思很简单 就是让你从n个数字中选取m个连续的数字使和最大 就是这样没错 因为是环状的 所以可以从末尾连到最开始
PS: 如果你觉得写得一定没有错 但还是wa 你可能忽略了 long long 没错 恭喜你!!!(还要注意最后 MOD n)
方法一 : 可以用前缀和 遍历一遍得到最大值和边界问题
#include <iostream>
#include <algorithm>
#include <cstring>
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 <iostream>
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;
}
}
没错我把两种方法对应反了 你以为我是不小心的?? 笑话 我怎么可能没发现 我就是故意的 就是这么傲娇