using namespace std;
// 直接暴力枚举
void consecutive_sum()
{
// 每次ij区间数组都重新求和
// n 500 tot 20958500
// 数组赋值
srand(time(NULL));
int n;
scanf("%d", &n);
int A[n];
for(int i = 0; i < n; i++) A[i] = (rand()%20-10);
// 求最长和
int tot = 0; // 累计加法次数
int longest = A[0];
int sum = 0;
for(int i = 0; i < n; i++)
for(int j = i; j < n; j++)
{
sum = 0;
for(int k = i; k <= j; k++)
{ sum += A[k]; tot++; }
if(sum > longest) longest = sum;
}
printf("\n%d %d", longest, tot);
}
// 暴力优化
void consecutive_sum1()
{
// Sij = S[i] - S[j]
// 事先保存0-i的S就可以不用每次重新求和
// n 500 tot 125749
// 数组赋值
int n;
scanf("%d", &n);
int A[n];
srand(time(NULL));
for(int i = 0; i < n; i++) { A[i] = rand()%20-10; printf("%d ", A[i]); }
// sum数组赋值
int sum[n];
sum[0] = A[0];
int tot = 0; // 累计加法次数
for(int i = 1; i < n; i++) { sum[i] = sum[i-1] + A[i]; tot++; }
// 求最长和
int longest = A[0];
for(int i = 1; i < n; i++)
for(int j = i-1; j >= -1; j--)
{ longest = max(longest, sum[i] - ((j == -1) ? 0 : sum[j])); tot++; }
printf("\n%d %d", longest, tot);
}
// 暴力再优化
void consecutive_sum3()
{
// 上面虽然优化了枚举,但还是要枚举j(0-i)到i的所有可能连续长度,求其中的最长长度
// 如果i是固定的,要使S[i]-S[j]最大,上面一种是直接j从i-1到0枚举
// 其实可以事先保存S[i]前面的最小连串,就可以使得S[i]-S[j]最大
int n;
scanf("%d", &n);
srand(time(NULL));
int A[n];
for(int i = 0; i < n; i++) { A[i] = rand()%20-10; printf("%d ", A[i]); }
int sum[n];
sum[0] = A[0];
for(int i = 1; i < n; i++) sum[i] = sum[i-1] + A[i];
int smallest[n];
smallest[0] = A[0];
for(int i = 1; i < n; i++) smallest[i] = min(smallest[i-1], sum[i]);
int longest = A[0];
for(int i = 1; i < n; i++) longest = max(max(longest, sum[i] - smallest[i-1]), sum[i]);
printf("\n%d", longest);
}
// 分治
// 返回数组闭区间 [x, y] 的最大连续和
// 有人用左闭右开区间 [x, y)
int daq(int *A, int x, int y)
{
// 一个值时递归结束
if(x == y) return A[x];
// 分区间,分别递归求两区间最大连续和
int m = x + (y-x)/2;
int llongest = daq(A, x, m);
int rlongest = daq(A, m+1, y);
int lrlongest = max(llongest, rlongest);
// 合并,分别求左右区间最大连续和并相加
int lclongest = A[m], temp = 0;
for(int i = m; i >= x; i--) lclongest = max(lclongest, temp += A[i]); // 赋值运算本身具有返回值
int rcolongest = A[m+1], temp1 = 0;
for(int i = m+1; i <= y; i++) rcolongest = max(rcolongest, temp1 += A[i]);
// 取最大返回
return max(lrlongest, lclongest+rcolongest);
}
void consecutive_sum2()
{
int n;
scanf("%d", &n);
srand(time(NULL));
int A[n];
for(int i = 0; i < n; i++) { A[i] = rand()%20-10; printf("%d ", A[i]); }
int longest = daq(A, 0, n-1);
printf("\n%d", longest);
}
int main()
{
consecutive_sum2();
return 0;
}