|
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