题目描述:
给你一个整数数组 nums 和一个二维数组 queries,其中 queries[i] = [posi, xi]。
对于每个查询 i,首先将 nums[posi] 设置为 xi,然后计算查询 i 的答案,该答案为 nums 中 不包含相邻元素 的 子序列的 最大 和。
返回所有查询的答案之和。
由于最终答案可能非常大,返回其对( 10^9 + 7 )取余 的结果。
子序列 是指从另一个数组中删除一些或不删除元素而不改变剩余元素顺序得到的数组。
示例 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 。
示例 2:
输入:nums = [0,-1], queries = [[0,-5]]
输出:0
解释:
执行第 1 个查询后,nums = [-5,-1],不包含相邻元素的子序列的最大和为 0(选择空子序列)。
解题思路
该题核心思想是通过线段树高效地处理区间更新和查询操作,从而在每次更新后快速计算出不包含相邻元素的子序列的最大和。具体步骤如下:
- 构建线段树。
- 对于每个查询,更新线段树中的相应元素。
- 计算更新后的线段树根节点的最大值,并累加到结果中。
- 返回最终结果。
代码实现
#include <bits/stdc++.h>
using namespace std;
constexpr int MOD = 1e9 + 7;
constexpr long long INF = 1e15;
struct SegmentTree {
struct Node {
array<long long, 4> a;
Node() : a{-INF, -INF, -INF, -INF} {}
Node operator+(Node& rhs) {
Node res;
auto _max = [](auto& x, auto y) {
x = max(x, y);
};
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
if(a[i] == -INF || rhs.a[j] == -INF) {
continue;
}
int i1 = i / 2, i2 = i % 2;
int j1 = j / 2, j2 = j % 2;
if (i2 == j1 && i2 == 1) {
continue;
}
int k1 = i1, k2 = j2;
_max(res.a[k1 * 2 + k2], a[i] + rhs.a[j]);
}
}
return res;
}
long long get() {
long long res = -INF;
for (auto x : a) {
res = max(res, x);
}
return res;
}
};
vector<Node> dat;
SegmentTree(vector<int>& a) {
int n = a.size();
int k = 1;
while (k < n) {
k *= 2;
}
k *= 2;
dat.resize(k);
function<void(int, int, int)> init = [&](int p, int l, int r) {
if (r - l == 1) {
dat[p].a = {0, -INF, -INF, a[l]};
return;
}
int m = (l + r) / 2;
int chl = p * 2 + 1, chr = p * 2 + 2;
init(chl, l, m);
init(chr, m, r);
dat[p] = dat[chl] + dat[chr];
};
init(0, 0, n);
}
void update(int a, int b, int x, int p, int l, int r) {
if (a <= l && r <= b) {
dat[p].a = {0, -INF, -INF, x};
return;
}
if (r <= a || b <= l) {
return;
}
int m = (l + r) / 2;
int chl = p * 2 + 1, chr = p * 2 + 2;
update(a, b, x, chl, l, m);
update(a, b, x, chr, m, r);
dat[p] = dat[chl] + dat[chr];
}
};
class Solution {
public:
int maximumSumSubsequence(vector<int>& nums, vector<vector<int>>& queries) {
int n = nums.size();
SegmentTree tr(nums);
int m = queries.size();
long long res = 0;
for (int i = 0; i < m; ++i) {
int j = queries[i][0], x = queries[i][1];
tr.update(j, j + 1, x, 0, 0, n);
res += tr.dat[0].get();
res %= MOD;
}
return (res + MOD) % MOD;
}
};

8万+

被折叠的 条评论
为什么被折叠?



