Smooth Subsequence(光滑的子序列)
时间限制:2s 内存限制:1024MB
【原题地址】
所有图片源自Atcoder,题目译文源自脚本Atcoder Better!
点击此处跳转至原题
【问题描述】
【输入格式】
【输出格式】
【样例1】
【样例输入1】
4 2
3 5 1 2
【样例输出1】
3
【样例说明1】
【样例2】
【样例输入2】
5 10
10 20 100 110 120
【样例输出2】
3
【样例3】
【样例输入3】
11 7
21 10 3 19 28 12 11 3 3 15 16
【样例输出3】
6
【解题思路】
老汉使用到的是DP+线段树优化的解题方式
代码注释有详细过程
【代码】
package ABC339_E_SmoothSubsequence;import java.util.Scanner;public class Main {static int[] tree = new int[500005];static int[] a = new int[500005];static int N = 500000;public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt();int d = scan.nextInt();int ans = 0;for (int i = 0; i < n; i++) {// 获取题目数组数据int num = scan.nextInt();// 左、右边界不超出数据限制时为当前数据符合条件的极限值int L = Math.max(1, num - d);int R = Math.min(N, num + d);// 查找这个区间内,对应之前出现的符合条件的数据已经连成的最大个数与不属于该范围已经连成的最大个数的最大值int res = query(L, R);// 当加上这个数后的个数大于之前同样出现过该数时连成的最大值时,更新对应数据if (res + 1 > a[num]) {update(num, res + 1);a[num] = res + 1;ans = Math.max(ans, res + 1);}}System.out.println(ans);scan.close();}/*** 求x二进制下的最低位的1代表的值* * @param x* @return x二进制下最低位的1代表的值*/public static int lowbit(int x) {return x & (-x);}/*** 更新所有与tree[x]有关联的所有上级节点数据* * @param x 结点下标* @param value 新的数据*/public static void update(int x, int value) {while (x <= N) {tree[x] = Math.max(value, tree[x]);x += lowbit(x);}}/*** 查找这个区间内,对应之前出现的符合条件的数据已经连成的最大个数与不属于该范围已经连成的最大个数的最大值* * @param L 左边界* @param R 右边界* @return 该区间符合条件的个数*/public static int query(int L, int R) {int ans = 0;while (L <= R) {ans = Math.max(ans, a[R]);R--;while (R - L >= lowbit(R)) {ans = Math.max(ans, tree[R]);R -= lowbit(R);}}return ans;}
}