java中的最大前缀,AcWing 1051. 最大的和 (Java 前后缀分解?)

思路

先分别求出顺序和逆序时,仅考虑前$i$个且且以$a_i$结尾的连续子序列最大和,记为$f_i$、$fr_i$

同样分别顺序和逆序处理上步得到的状态数组,改造为“仅考虑前$i$个但不限制$a_i$结尾的连续子序列最大和”

枚举分界点,将数组分为两段$a_1 \sim a_k$、$a_{k+1} \sim a_n$,根据状态数组求左段顺序最大和$f_k$、右段逆序最大和$fr_{k+1}$

代码

import java.util.*;

import java.lang.*;

public class Main {

static Scanner scanner = new Scanner(System.in);

static int t, n, N = 50010;

static long[] a = new long[N], f = new long[N], fr = new long[N];

public static void main(String[] args) {

t = scanner.nextInt();

for (int k = 1; k <= t; k++) {

Arrays.fill(f, 0); // 状态初始化

Arrays.fill(fr, 0);

n = scanner.nextInt();

for (int i = 1; i <= n; i++) a[i] = scanner.nextInt(); // 读数

// 顺序求 只考虑前i个且以a[i]结尾的连续子序列最大和

for (int i = 1; i <= n; i++) f[i] = Math.max(0, f[i - 1]) + a[i];

// 逆序求 只考虑后i个·····

for (int i = n; i >= 1; i--) fr[i] = Math.max(0, fr[i + 1]) + a[i];

// 顺序遍历 将状态数组改为 “只考虑前i个数,能得到的连续子序列最大和”

for (int i = 2; i <= n; i++) f[i] = Math.max(f[i], f[i - 1]);

// 逆序遍历 ····

for (int i = n - 1; i >= 1; i--) fr[i] = Math.max(fr[i], fr[i + 1]);

long res = Long.MIN_VALUE;

// 枚举分界点 将数组分为顺序【1,i】、逆序【i+1,n】两段 两段最大和相加即为最终答案

for (int i = 1; i < n; i++) res = Math.max(res, f[i] + fr[i + 1]);

System.out.println(res);

}

}

}

你可能感兴趣的:(java中的最大前缀)