Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,125 +1,77 @@
package g3101_3200.s3165_maximum_sum_of_subsequence_with_non_adjacent_elements;

// #Hard #Array #Dynamic_Programming #Divide_and_Conquer #Segment_Tree
// #2024_06_02_Time_1927_ms_(87.75%)_Space_82.1_MB_(5.31%)

import java.util.stream.Stream;
// #2024_11_09_Time_64_ms_(100.00%)_Space_64.1_MB_(97.01%)

public class Solution {
private static final int YY = 0;
private static final int YN = 1;
private static final int NY = 2;
private static final int NN = 3;
private static final int MOD = 1_000_000_007;

public int maximumSumSubsequence(int[] nums, int[][] queries) {
int ans = 0;
SegTree segTree = new SegTree(nums);
for (int[] q : queries) {
int idx = q[0];
int val = q[1];
segTree.update(idx, val);
ans = (ans + segTree.getMax()) % MOD;
long[][] tree = build(nums);
long result = 0;
for (int i = 0; i < queries.length; ++i) {
result += set(tree, queries[i][0], queries[i][1]);
result %= MOD;
}
return ans;
return (int) result;
}

static class SegTree {
private static class Record {
int takeFirstTakeLast;
int takeFirstSkipLast;
int skipFirstSkipLast;
int skipFirstTakeLast;

public Integer getMax() {
return Stream.of(
this.takeFirstSkipLast,
this.takeFirstTakeLast,
this.skipFirstSkipLast,
this.skipFirstTakeLast)
.max(Integer::compare)
.orElse(null);
}

public Integer skipLast() {
return Stream.of(this.takeFirstSkipLast, this.skipFirstSkipLast)
.max(Integer::compare)
.orElse(null);
}

public Integer takeLast() {
return Stream.of(this.skipFirstTakeLast, this.takeFirstTakeLast)
.max(Integer::compare)
.orElse(null);
}
private static long[][] build(int[] nums) {
final int len = nums.length;
int size = 1;
while (size < len) {
size <<= 1;
}

private final Record[] seg;
private final int[] nums;

public SegTree(int[] nums) {
this.nums = nums;
seg = new Record[4 * nums.length];
for (int i = 0; i < 4 * nums.length; ++i) {
seg[i] = new Record();
}
build(0, nums.length - 1, 0);
long[][] tree = new long[size * 2][4];
for (int i = 0; i < len; ++i) {
tree[size + i][YY] = nums[i];
}

private void build(int i, int j, int k) {
if (i == j) {
seg[k].takeFirstTakeLast = nums[i];
return;
}
int mid = (i + j) >> 1;
build(i, mid, 2 * k + 1);
build(mid + 1, j, 2 * k + 2);
merge(k);
}

// merge [2*k+1, 2*k+2] into k
private void merge(int k) {
seg[k].takeFirstSkipLast =
for (int i = size - 1; i > 0; --i) {
tree[i][YY] =
Math.max(
seg[2 * k + 1].takeFirstSkipLast + seg[2 * k + 2].skipLast(),
seg[2 * k + 1].takeFirstTakeLast + seg[2 * k + 2].skipFirstSkipLast);

seg[k].takeFirstTakeLast =
tree[2 * i][YY] + tree[2 * i + 1][NY],
tree[2 * i][YN] + Math.max(tree[2 * i + 1][YY], tree[2 * i + 1][NY]));
tree[i][YN] =
Math.max(
seg[2 * k + 1].takeFirstSkipLast + seg[2 * k + 2].takeLast(),
seg[2 * k + 1].takeFirstTakeLast + seg[2 * k + 2].skipFirstTakeLast);

seg[k].skipFirstTakeLast =
tree[2 * i][YY] + tree[2 * i + 1][NN],
tree[2 * i][YN] + Math.max(tree[2 * i + 1][YN], tree[2 * i + 1][NN]));
tree[i][NY] =
Math.max(
seg[2 * k + 1].skipFirstSkipLast + seg[2 * k + 2].takeLast(),
seg[2 * k + 1].skipFirstTakeLast + seg[2 * k + 2].skipFirstTakeLast);

seg[k].skipFirstSkipLast =
tree[2 * i][NY] + tree[2 * i + 1][NY],
tree[2 * i][NN] + Math.max(tree[2 * i + 1][YY], tree[2 * i + 1][NY]));
tree[i][NN] =
Math.max(
seg[2 * k + 1].skipFirstSkipLast + seg[2 * k + 2].skipLast(),
seg[2 * k + 1].skipFirstTakeLast + seg[2 * k + 2].skipFirstSkipLast);
}

// child -> parent
public void update(int idx, int val) {
int i = 0;
int j = nums.length - 1;
int k = 0;
update(idx, val, k, i, j);
}

private void update(int idx, int val, int k, int i, int j) {
if (i == j) {
seg[k].takeFirstTakeLast = val;
return;
}
int mid = (i + j) >> 1;
if (idx <= mid) {
update(idx, val, 2 * k + 1, i, mid);
} else {
update(idx, val, 2 * k + 2, mid + 1, j);
}
merge(k);
tree[2 * i][NY] + tree[2 * i + 1][NN],
tree[2 * i][NN] + Math.max(tree[2 * i + 1][YN], tree[2 * i + 1][NN]));
}
return tree;
}

public int getMax() {
return seg[0].getMax();
private static long set(long[][] tree, int idx, int val) {
int size = tree.length / 2;
tree[size + idx][YY] = val;
for (int i = (size + idx) / 2; i > 0; i /= 2) {
tree[i][YY] =
Math.max(
tree[2 * i][YY] + tree[2 * i + 1][NY],
tree[2 * i][YN] + Math.max(tree[2 * i + 1][YY], tree[2 * i + 1][NY]));
tree[i][YN] =
Math.max(
tree[2 * i][YY] + tree[2 * i + 1][NN],
tree[2 * i][YN] + Math.max(tree[2 * i + 1][YN], tree[2 * i + 1][NN]));
tree[i][NY] =
Math.max(
tree[2 * i][NY] + tree[2 * i + 1][NY],
tree[2 * i][NN] + Math.max(tree[2 * i + 1][YY], tree[2 * i + 1][NY]));
tree[i][NN] =
Math.max(
tree[2 * i][NY] + tree[2 * i + 1][NN],
tree[2 * i][NN] + Math.max(tree[2 * i + 1][YN], tree[2 * i + 1][NN]));
}
return Math.max(tree[1][YY], Math.max(tree[1][YN], Math.max(tree[1][NY], tree[1][NN])));
}
}
Loading