3165. 不包含相邻元素的子序列的最大和(真心看不懂,先copy)
/**
* 3165题. 不包含相邻元素的子序列的最大和
* 给你一个整数数组 nums 和一个二维数组 queries,其中 queries[i] = [posi, xi]。
* 对于每个查询 i,首先将 nums[posi] 设置为 xi,然后计算查询 i 的答案,该答案为 nums 中 不包含相邻元素 的
* 子序列
* 的 最大 和。
* 返回所有查询的答案之和。
* 由于最终答案可能非常大,返回其对 109 + 7 取余 的结果。
* 子序列 是指从另一个数组中删除一些或不删除元素而不改变剩余元素顺序得到的数组。
* <p>
* 示例 1:
* 输入:nums = [3,5,9], queries = [[1,-2],[0,-3]]
* 输出:21
* 解释:
* 执行第 1 个查询后,nums = [3,-2,9],不包含相邻元素的子序列的最大和为 3 + 9 = 12。
* 执行第 2 个查询后,nums = [-3,-2,9],不包含相邻元素的子序列的最大和为 9 。
* <p>
* 示例 2:
* 输入:nums = [0,-1], queries = [[0,-5]]
* 输出:0
* 解释:
* 执行第 1 个查询后,nums = [-5,-1],不包含相邻元素的子序列的最大和为 0(选择空子序列)。
* <p>
* 提示:
* 1 <= nums.length <= 5 * 104
* -105 <= nums[i] <= 105
* 1 <= queries.length <= 5 * 104
* queries[i] == [posi, xi]
* 0 <= posi <= nums.length - 1
* -105 <= xi <= 105
*
* @since 2024-10-31
*/
public class LeetCode1031_3165 {
public static void main(String[] args) {
// 测试输出
int[] nums = {3, 5, 9};
// queries[i] = [posi, xi]。
int[][] queries = {{1, -2}, {0, -3}};
System.out.println(maximumSumSubsequence(nums, queries));
}
/**
* 作者:灵茶山艾府
* 链接:https://leetcode.cn/problems/maximum-sum-of-subsequence-with-non-adjacent-elements/solutions/2790603/fen-zhi-si-xiang-xian-duan-shu-pythonjav-xnhz/
* 来源:力扣(LeetCode)
* 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*
* @param nums
* @param queries
* @return
*/
public static int maximumSumSubsequence(int[] nums, int[][] queries) {
int n = nums.length;
// 4 个数分别保存 f00, f01, f10, f11
long[][] t = new long[2 << (32 - Integer.numberOfLeadingZeros(n))][4];
build(t, nums, 1, 0, n - 1);
long ans = 0;
for (int[] q : queries) {
update(t, 1, 0, n - 1, q[0], q[1]);
ans += t[1][3]; // 注意 f11 没有任何限制,也就是整个数组的打家劫舍
}
return (int) (ans % 1_000_000_007);
}
// 合并左右儿子
private static void maintain(long[][] t, int o) {
long[] a = t[o * 2];
long[] b = t[o * 2 + 1];
t[o][0] = Math.max(a[0] + b[2], a[1] + b[0]);
t[o][1] = Math.max(a[0] + b[3], a[1] + b[1]);
t[o][2] = Math.max(a[2] + b[2], a[3] + b[0]);
t[o][3] = Math.max(a[2] + b[3], a[3] + b[1]);
}
// 用 nums 初始化线段树
private static void build(long[][] t, int[] nums, int o, int l, int r) {
if (l == r) {
t[o][3] = Math.max(nums[l], 0);
return;
}
int m = (l + r) / 2;
build(t, nums, o * 2, l, m);
build(t, nums, o * 2 + 1, m + 1, r);
maintain(t, o);
}
// 把 nums[i] 改成 val
private static void update(long[][] t, int o, int l, int r, int i, int val) {
if (l == r) {
t[o][3] = Math.max(val, 0);
return;
}
int m = (l + r) / 2;
if (i <= m) {
update(t, o * 2, l, m, i, val);
} else {
update(t, o * 2 + 1, m + 1, r, i, val);
}
maintain(t, o);
}
}
本文来自博客园,作者:xiaolifc,转载请注明原文链接:https://www.cnblogs.com/xiaolibiji/p/18517846
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!