最大上升子序列和 (抄答案十分钟,debug两小时)【编程风格】
⭐ 原题地址


⭐ DP + 离散化 + 树状数组
🤬 切记:全局变量和局部变量同名的时候,在局部内局部变量优先! 【TMD】

import java.io.*;
import java.util.*;
public class Main
{
static int N = 100010, n;
static long[] tr = new long[N];// 树状数组维护区间最大值
static long[] f = new long[N];// DP数组
static int[] h = new int[N];// 离散化数组
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
static int lowbit(int x)
{
return x & -x;
}
static long query(int x)
{
long res = 0;
for (int i = x; i > 0; i -= lowbit(i))
{
res = Math.max(res, tr[i]);
}
return res;
}
static void add(int x, long c)
{
for (int i = x; i <= n; i += lowbit(i))
{
tr[i] = Math.max(tr[i], c);
}
}
public static void main(String[] args) throws IOException
{
// 错误示范
// int n = Integer.parseInt(in.readLine()); // 变量重定义导致全局变量没有get到值,我是垃圾
n = Integer.parseInt(in.readLine());
int[] w = new int[n];
String[] ss = in.readLine().split(" ");
// 输入原序列
for (int i = 0; i < n; i++)
w[i] = Integer.parseInt(ss[i]);
// for (int i = 0; i < n; i++)
// System.out.println(w[i]);
// 输入测试
// Scanner sc = new Scanner(System.in);
// n = sc.nextInt();
// int[] w = new int[n];
// for (int i = 0; i < n; i++)
// {
// w[i] = sc.nextInt();
// }
// 离散化
solve(w);
// System.out.print("w[] = ");
// for (int i = 0; i < n; i++)
// System.out.print(w[i] + " ");
// System.out.println();
// 求解
long res = 0;
for (int i = 0; i < n; i++)
{
// 离散化后的下标
int k = h[i];
f[i] = query(k - 1) + w[i];
// System.out.println(i + " " + k + " " + query(k - 1) + " " + f[i]); //输出调试
res = Math.max(res, f[i]);
add(k, f[i]);//更新符合题目条件的前缀和
}
System.out.println(res);
}
private static void solve(int[] w)
{
SortedSet<Integer> set = new TreeSet<>();
for (int a : w)
{
set.add(a);
}
int[] c = new int[set.size()];
int cnt = 0;
for (int s : set)
{
c[cnt++] = s;
}
for (int i = 0; i < w.length; i++)
{
h[i] = Arrays.binarySearch(c, w[i]) + 1;
}
}
}

浙公网安备 33010602011771号