|
1 | 1 | package g3101_3200.s3165_maximum_sum_of_subsequence_with_non_adjacent_elements;
|
2 | 2 |
|
3 | 3 | // #Hard #Array #Dynamic_Programming #Divide_and_Conquer #Segment_Tree
|
4 | | -// #2024_06_02_Time_1927_ms_(87.75%)_Space_82.1_MB_(5.31%) |
5 | | - |
6 | | -import java.util.stream.Stream; |
| 4 | +// #2024_11_09_Time_64_ms_(100.00%)_Space_64.1_MB_(97.01%) |
7 | 5 |
|
8 | 6 | public class Solution {
|
| 7 | + private static final int YY = 0; |
| 8 | + private static final int YN = 1; |
| 9 | + private static final int NY = 2; |
| 10 | + private static final int NN = 3; |
9 | 11 | private static final int MOD = 1_000_000_007;
|
10 | 12 |
|
11 | 13 | public int maximumSumSubsequence(int[] nums, int[][] queries) {
|
12 | | - int ans = 0; |
13 | | - SegTree segTree = new SegTree(nums); |
14 | | - for (int[] q : queries) { |
15 | | - int idx = q[0]; |
16 | | - int val = q[1]; |
17 | | - segTree.update(idx, val); |
18 | | - ans = (ans + segTree.getMax()) % MOD; |
| 14 | + long[][] tree = build(nums); |
| 15 | + long result = 0; |
| 16 | + for (int i = 0; i < queries.length; ++i) { |
| 17 | + result += set(tree, queries[i][0], queries[i][1]); |
| 18 | + result %= MOD; |
19 | 19 | }
|
20 | | - return ans; |
| 20 | + return (int) result; |
21 | 21 | }
|
22 | 22 |
|
23 | | - static class SegTree { |
24 | | - private static class Record { |
25 | | - int takeFirstTakeLast; |
26 | | - int takeFirstSkipLast; |
27 | | - int skipFirstSkipLast; |
28 | | - int skipFirstTakeLast; |
29 | | - |
30 | | - public Integer getMax() { |
31 | | - return Stream.of( |
32 | | - this.takeFirstSkipLast, |
33 | | - this.takeFirstTakeLast, |
34 | | - this.skipFirstSkipLast, |
35 | | - this.skipFirstTakeLast) |
36 | | - .max(Integer::compare) |
37 | | - .orElse(null); |
38 | | - } |
39 | | - |
40 | | - public Integer skipLast() { |
41 | | - return Stream.of(this.takeFirstSkipLast, this.skipFirstSkipLast) |
42 | | - .max(Integer::compare) |
43 | | - .orElse(null); |
44 | | - } |
45 | | - |
46 | | - public Integer takeLast() { |
47 | | - return Stream.of(this.skipFirstTakeLast, this.takeFirstTakeLast) |
48 | | - .max(Integer::compare) |
49 | | - .orElse(null); |
50 | | - } |
| 23 | + private static long[][] build(int[] nums) { |
| 24 | + final int len = nums.length; |
| 25 | + int size = 1; |
| 26 | + while (size < len) { |
| 27 | + size <<= 1; |
51 | 28 | }
|
52 | | - |
53 | | - private final Record[] seg; |
54 | | - private final int[] nums; |
55 | | - |
56 | | - public SegTree(int[] nums) { |
57 | | - this.nums = nums; |
58 | | - seg = new Record[4 * nums.length]; |
59 | | - for (int i = 0; i < 4 * nums.length; ++i) { |
60 | | - seg[i] = new Record(); |
61 | | - } |
62 | | - build(0, nums.length - 1, 0); |
| 29 | + long[][] tree = new long[size * 2][4]; |
| 30 | + for (int i = 0; i < len; ++i) { |
| 31 | + tree[size + i][YY] = nums[i]; |
63 | 32 | }
|
64 | | - |
65 | | - private void build(int i, int j, int k) { |
66 | | - if (i == j) { |
67 | | - seg[k].takeFirstTakeLast = nums[i]; |
68 | | - return; |
69 | | - } |
70 | | - int mid = (i + j) >> 1; |
71 | | - build(i, mid, 2 * k + 1); |
72 | | - build(mid + 1, j, 2 * k + 2); |
73 | | - merge(k); |
74 | | - } |
75 | | - |
76 | | - // merge [2*k+1, 2*k+2] into k |
77 | | - private void merge(int k) { |
78 | | - seg[k].takeFirstSkipLast = |
| 33 | + for (int i = size - 1; i > 0; --i) { |
| 34 | + tree[i][YY] = |
79 | 35 | Math.max(
|
80 | | - seg[2 * k + 1].takeFirstSkipLast + seg[2 * k + 2].skipLast(), |
81 | | - seg[2 * k + 1].takeFirstTakeLast + seg[2 * k + 2].skipFirstSkipLast); |
82 | | - |
83 | | - seg[k].takeFirstTakeLast = |
| 36 | + tree[2 * i][YY] + tree[2 * i + 1][NY], |
| 37 | + tree[2 * i][YN] + Math.max(tree[2 * i + 1][YY], tree[2 * i + 1][NY])); |
| 38 | + tree[i][YN] = |
84 | 39 | Math.max(
|
85 | | - seg[2 * k + 1].takeFirstSkipLast + seg[2 * k + 2].takeLast(), |
86 | | - seg[2 * k + 1].takeFirstTakeLast + seg[2 * k + 2].skipFirstTakeLast); |
87 | | - |
88 | | - seg[k].skipFirstTakeLast = |
| 40 | + tree[2 * i][YY] + tree[2 * i + 1][NN], |
| 41 | + tree[2 * i][YN] + Math.max(tree[2 * i + 1][YN], tree[2 * i + 1][NN])); |
| 42 | + tree[i][NY] = |
89 | 43 | Math.max(
|
90 | | - seg[2 * k + 1].skipFirstSkipLast + seg[2 * k + 2].takeLast(), |
91 | | - seg[2 * k + 1].skipFirstTakeLast + seg[2 * k + 2].skipFirstTakeLast); |
92 | | - |
93 | | - seg[k].skipFirstSkipLast = |
| 44 | + tree[2 * i][NY] + tree[2 * i + 1][NY], |
| 45 | + tree[2 * i][NN] + Math.max(tree[2 * i + 1][YY], tree[2 * i + 1][NY])); |
| 46 | + tree[i][NN] = |
94 | 47 | Math.max(
|
95 | | - seg[2 * k + 1].skipFirstSkipLast + seg[2 * k + 2].skipLast(), |
96 | | - seg[2 * k + 1].skipFirstTakeLast + seg[2 * k + 2].skipFirstSkipLast); |
97 | | - } |
98 | | - |
99 | | - // child -> parent |
100 | | - public void update(int idx, int val) { |
101 | | - int i = 0; |
102 | | - int j = nums.length - 1; |
103 | | - int k = 0; |
104 | | - update(idx, val, k, i, j); |
105 | | - } |
106 | | - |
107 | | - private void update(int idx, int val, int k, int i, int j) { |
108 | | - if (i == j) { |
109 | | - seg[k].takeFirstTakeLast = val; |
110 | | - return; |
111 | | - } |
112 | | - int mid = (i + j) >> 1; |
113 | | - if (idx <= mid) { |
114 | | - update(idx, val, 2 * k + 1, i, mid); |
115 | | - } else { |
116 | | - update(idx, val, 2 * k + 2, mid + 1, j); |
117 | | - } |
118 | | - merge(k); |
| 48 | + tree[2 * i][NY] + tree[2 * i + 1][NN], |
| 49 | + tree[2 * i][NN] + Math.max(tree[2 * i + 1][YN], tree[2 * i + 1][NN])); |
119 | 50 | }
|
| 51 | + return tree; |
| 52 | + } |
120 | 53 |
|
121 | | - public int getMax() { |
122 | | - return seg[0].getMax(); |
| 54 | + private static long set(long[][] tree, int idx, int val) { |
| 55 | + int size = tree.length / 2; |
| 56 | + tree[size + idx][YY] = val; |
| 57 | + for (int i = (size + idx) / 2; i > 0; i /= 2) { |
| 58 | + tree[i][YY] = |
| 59 | + Math.max( |
| 60 | + tree[2 * i][YY] + tree[2 * i + 1][NY], |
| 61 | + tree[2 * i][YN] + Math.max(tree[2 * i + 1][YY], tree[2 * i + 1][NY])); |
| 62 | + tree[i][YN] = |
| 63 | + Math.max( |
| 64 | + tree[2 * i][YY] + tree[2 * i + 1][NN], |
| 65 | + tree[2 * i][YN] + Math.max(tree[2 * i + 1][YN], tree[2 * i + 1][NN])); |
| 66 | + tree[i][NY] = |
| 67 | + Math.max( |
| 68 | + tree[2 * i][NY] + tree[2 * i + 1][NY], |
| 69 | + tree[2 * i][NN] + Math.max(tree[2 * i + 1][YY], tree[2 * i + 1][NY])); |
| 70 | + tree[i][NN] = |
| 71 | + Math.max( |
| 72 | + tree[2 * i][NY] + tree[2 * i + 1][NN], |
| 73 | + tree[2 * i][NN] + Math.max(tree[2 * i + 1][YN], tree[2 * i + 1][NN])); |
123 | 74 | }
|
| 75 | + return Math.max(tree[1][YY], Math.max(tree[1][YN], Math.max(tree[1][NY], tree[1][NN]))); |
124 | 76 | }
|
125 | 77 | }
|
0 commit comments