第一篇博客,背景:为了五月的省赛叮当猫要求洛谷刷题,我刷的很慢而且不喜欢总结,手写潦草而且慢;想到这里都是大神,以前题解都是来这找的,遂想自己把总结写到这里,话不多说,有什么话以后再说。
题目描述
给出一段序列,选出其中连续且非空的一段使得这段和最大。
输入输出格式
输入格式:
输入文件maxsum1.in的第一行是一个正整数N,表示了序列的长度。
第2行包含N个绝对值不大于10000的整数A[i],描述了这段序列。
输出格式:
输入文件maxsum1.out仅包括1个整数,为最大的子段和是多少。子段的最小长度为1。
输入输出样例
输入样例#1:复制
7
2 -4 3 -1 2 -4 3
输出样例#1:复制
4
说明
【样例说明】2 -4 3 -1 2 -4 3
【数据规模与约定】
对于40%的数据,有N ≤ 2000。
对于100%的数据,有N ≤ 200000。
///分割线
#include <bits/stdc++.h>
//最大字段和, 我以前做过用的递归没想到如何O(n), 今天看到大佬代码与以前思路相同, 大佬已经实现
int main(){
int n;
int N[2000 + 5];
cin >> n;
for (int i = 0; i < n; ++i) cin >> N[i];
int max = N[0], sum = 0;
if (max > 0) sum = max;
for (int i = 1; i < n; ++i) {
sum += N[i];
if (sum > max) max = sum;
if (sum < 0) sum = 0;
}
cout << max << endl;
return 0;
}
//又看到DP的思想, dp[i]数组用来存当前1~i最大的数
int main(){
int Max = - (1 << 30);
int n, N[200000 + 5] = {0}, dp[200000 + 5] = {0};
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> N[i];
dp[i] = max(dp[i - 1] + N[i], N[i]);
Max = max(Max, dp[i]);
}
cout << Max << endl;
return 0;
}
//再贴上我的源代码, 第二组样例错误
int n;
int N[200000 + 5];
int main(){
cin >> n;
for (int i = 0; i < n; ++i) cin >> N[i];
cout << fun(0, n - 1) << endl;
return 0;
}
int fun(int l, int r){
if (l == r) return N[l];
int min = (l + r) / 2;
int lmax = fun(l, min);
int rmax = fun(min + 1, r);
int max = lmax > rmax ? lmax : rmax;
int sum = 0, lsum = 0, rsum = 0;
for (int i = min; i >= l; --i) {
sum += N[i];
if (sum > lsum) lsum = sum;
}
sum = 0;
for (int i = min + 1; i <= r; ++i) {
sum += N[i];
if (sum > rsum) rsum = sum;
}
sum = lsum + rsum;
if (sum > max) return sum;
return max;
}