Skip to content

Commit fc37d31

Browse files
committed
Improved tasks 3510, 3515
1 parent 83c6fa9 commit fc37d31

File tree

2 files changed

+179
-162
lines changed
  • src/main/java/g3501_3600

2 files changed

+179
-162
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,104 @@
11
package g3501_3600.s3510_minimum_pair_removal_to_sort_array_ii;
22

33
// #Hard #Array #Hash_Table #Heap_Priority_Queue #Simulation #Linked_List #Ordered_Set
4-
// #Doubly_Linked_List #2025_04_09_Time_289_ms_(99.58%)_Space_82.88_MB_(17.23%)
4+
// #Doubly_Linked_List #2025_04_29_Time_274_ms_(98.94%)_Space_70.73_MB_(69.15%)
55

6-
public class Solution {
7-
private static class Segment {
8-
private final int start;
9-
private final int end;
10-
private Segment left;
11-
private Segment right;
12-
private int lIdx;
13-
private long lNum;
14-
private int rIdx;
15-
private long rNum;
16-
private boolean ok;
17-
private long minSum;
18-
private int li;
19-
private int ri;
6+
import java.util.Arrays;
207

21-
public static Segment init(int[] arr) {
22-
return new Segment(arr, 0, arr.length - 1);
8+
public class Solution {
9+
public int minimumPairRemoval(int[] nums) {
10+
if (nums.length == 1) {
11+
return 0;
2312
}
24-
25-
public Segment(int[] arr, int s, int e) {
26-
start = s;
27-
end = e;
28-
if (s >= e) {
29-
lIdx = rIdx = s;
30-
lNum = rNum = arr[s];
31-
minSum = Long.MAX_VALUE;
32-
ok = true;
33-
return;
13+
int size = (int) Math.pow(2, Math.ceil(Math.log(nums.length - 1) / Math.log(2)));
14+
long[] segment = new long[size * 2 - 1];
15+
Arrays.fill(segment, Long.MAX_VALUE);
16+
int[] lefts = new int[size * 2 - 1];
17+
int[] rights = new int[size * 2 - 1];
18+
long[] sums = new long[nums.length];
19+
Arrays.fill(sums, Long.MAX_VALUE / 2);
20+
int[][] arrIdxToSegIdx = new int[nums.length][];
21+
boolean[] isDecs = new boolean[nums.length];
22+
sums[0] = nums[0];
23+
int count = 0;
24+
arrIdxToSegIdx[0] = new int[] {-1, size - 1};
25+
for (int i = 1; i < nums.length; i++) {
26+
if (nums[i] < nums[i - 1]) {
27+
isDecs[i] = true;
28+
count++;
3429
}
35-
int mid = s + ((e - s) >> 1);
36-
left = new Segment(arr, s, mid);
37-
right = new Segment(arr, mid + 1, e);
38-
merge();
30+
lefts[size + i - 2] = i - 1;
31+
rights[size + i - 2] = i;
32+
segment[size + i - 2] = nums[i - 1] + nums[i];
33+
arrIdxToSegIdx[i] = new int[] {size + i - 2, size + i - 1};
34+
sums[i] = nums[i];
3935
}
40-
41-
private void merge() {
42-
lIdx = left.lIdx;
43-
lNum = left.lNum;
44-
rIdx = right.rIdx;
45-
rNum = right.rNum;
46-
ok = left.ok && right.ok && left.rNum <= right.lNum;
47-
minSum = left.minSum;
48-
li = left.li;
49-
ri = left.ri;
50-
if (left.rNum + right.lNum < minSum) {
51-
minSum = left.rNum + right.lNum;
52-
li = left.rIdx;
53-
ri = right.lIdx;
54-
}
55-
if (right.minSum < minSum) {
56-
minSum = right.minSum;
57-
li = right.li;
58-
ri = right.ri;
59-
}
36+
arrIdxToSegIdx[nums.length - 1][1] = -1;
37+
for (int i = size - 2; i >= 0; i--) {
38+
int l = 2 * i + 1;
39+
int r = 2 * i + 2;
40+
segment[i] = Math.min(segment[l], segment[r]);
6041
}
61-
62-
public void update(int i, long n) {
63-
if (start <= i && end >= i) {
64-
if (start >= end) {
65-
lNum = rNum = n;
42+
int res = 0;
43+
while (count > 0) {
44+
int segIdx = 0;
45+
while (2 * segIdx + 1 < segment.length) {
46+
int l = 2 * segIdx + 1;
47+
int r = 2 * segIdx + 2;
48+
if (segment[l] <= segment[r]) {
49+
segIdx = l;
6650
} else {
67-
left.update(i, n);
68-
right.update(i, n);
69-
merge();
51+
segIdx = r;
7052
}
7153
}
72-
}
73-
74-
public Segment remove(int i) {
75-
if (start > i || end < i) {
76-
return this;
77-
} else if (start >= end) {
78-
return null;
54+
int arrIdxL = lefts[segIdx];
55+
int arrIdxR = rights[segIdx];
56+
long numL = sums[arrIdxL];
57+
long numR = sums[arrIdxR];
58+
if (numL > numR) {
59+
count--;
7960
}
80-
left = left.remove(i);
81-
right = right.remove(i);
82-
if (null == left) {
83-
return right;
84-
} else if (null == right) {
85-
return left;
61+
long newSum = sums[arrIdxL] = sums[arrIdxL] + sums[arrIdxR];
62+
int[] leftPointer = arrIdxToSegIdx[arrIdxL];
63+
int[] rightPointer = arrIdxToSegIdx[arrIdxR];
64+
int prvSegIdx = leftPointer[0];
65+
int nextSegIdx = rightPointer[1];
66+
leftPointer[1] = nextSegIdx;
67+
if (prvSegIdx != -1) {
68+
int l = lefts[prvSegIdx];
69+
if (sums[l] > numL && sums[l] <= newSum) {
70+
count--;
71+
} else if (sums[l] <= numL && sums[l] > newSum) {
72+
count++;
73+
}
74+
modify(segment, prvSegIdx, sums[l] + newSum);
75+
}
76+
if (nextSegIdx != -1) {
77+
int r = rights[nextSegIdx];
78+
if (numR > sums[r] && newSum <= sums[r]) {
79+
count--;
80+
} else if (numR <= sums[r] && newSum > sums[r]) {
81+
count++;
82+
}
83+
modify(segment, nextSegIdx, newSum + sums[r]);
84+
lefts[nextSegIdx] = arrIdxL;
8685
}
87-
merge();
88-
return this;
86+
modify(segment, segIdx, Long.MAX_VALUE);
87+
res++;
8988
}
89+
return res;
9090
}
9191

92-
public int minimumPairRemoval(int[] nums) {
93-
Segment root = Segment.init(nums);
94-
int res = 0;
95-
while (!root.ok) {
96-
int l = root.li;
97-
int r = root.ri;
98-
root.update(l, root.minSum);
99-
root = root.remove(r);
100-
res++;
92+
private void modify(long[] segment, int idx, long num) {
93+
if (segment[idx] == num) {
94+
return;
95+
}
96+
segment[idx] = num;
97+
while (idx != 0) {
98+
idx = (idx - 1) / 2;
99+
int l = 2 * idx + 1;
100+
int r = 2 * idx + 2;
101+
segment[idx] = Math.min(segment[l], segment[r]);
101102
}
102-
return res;
103103
}
104104
}

0 commit comments

Comments
 (0)