Skip to content

Commit 8fef545

Browse files
authored
Improved tasks 3510, 3515
1 parent 83c6fa9 commit 8fef545

File tree

3 files changed

+203
-161
lines changed

3 files changed

+203
-161
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,112 @@
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_278_ms_(98.94%)_Space_70.90_MB_(68.88%)
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.0) / 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+
sums[0] = nums[0];
22+
int count = 0;
23+
arrIdxToSegIdx[0] = new int[] {-1, size - 1};
24+
for (int i = 1; i < nums.length; i++) {
25+
if (nums[i] < nums[i - 1]) {
26+
count++;
3427
}
35-
int mid = s + ((e - s) >> 1);
36-
left = new Segment(arr, s, mid);
37-
right = new Segment(arr, mid + 1, e);
38-
merge();
28+
lefts[size + i - 2] = i - 1;
29+
rights[size + i - 2] = i;
30+
segment[size + i - 2] = nums[i - 1] + (long) nums[i];
31+
arrIdxToSegIdx[i] = new int[] {size + i - 2, size + i - 1};
32+
sums[i] = nums[i];
3933
}
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-
}
34+
arrIdxToSegIdx[nums.length - 1][1] = -1;
35+
for (int i = size - 2; i >= 0; i--) {
36+
int l = 2 * i + 1;
37+
int r = 2 * i + 2;
38+
segment[i] = Math.min(segment[l], segment[r]);
6039
}
40+
return getRes(count, segment, lefts, rights, sums, arrIdxToSegIdx);
41+
}
6142

62-
public void update(int i, long n) {
63-
if (start <= i && end >= i) {
64-
if (start >= end) {
65-
lNum = rNum = n;
43+
private int getRes(
44+
int count,
45+
long[] segment,
46+
int[] lefts,
47+
int[] rights,
48+
long[] sums,
49+
int[][] arrIdxToSegIdx) {
50+
int res = 0;
51+
while (count > 0) {
52+
int segIdx = 0;
53+
while (2 * segIdx + 1 < segment.length) {
54+
int l = 2 * segIdx + 1;
55+
int r = 2 * segIdx + 2;
56+
if (segment[l] <= segment[r]) {
57+
segIdx = l;
6658
} else {
67-
left.update(i, n);
68-
right.update(i, n);
69-
merge();
59+
segIdx = r;
7060
}
7161
}
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;
62+
int arrIdxL = lefts[segIdx];
63+
int arrIdxR = rights[segIdx];
64+
long numL = sums[arrIdxL];
65+
long numR = sums[arrIdxR];
66+
if (numL > numR) {
67+
count--;
7968
}
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;
69+
long newSum = sums[arrIdxL] = sums[arrIdxL] + sums[arrIdxR];
70+
int[] leftPointer = arrIdxToSegIdx[arrIdxL];
71+
int[] rightPointer = arrIdxToSegIdx[arrIdxR];
72+
int prvSegIdx = leftPointer[0];
73+
int nextSegIdx = rightPointer[1];
74+
leftPointer[1] = nextSegIdx;
75+
if (prvSegIdx != -1) {
76+
int l = lefts[prvSegIdx];
77+
if (sums[l] > numL && sums[l] <= newSum) {
78+
count--;
79+
} else if (sums[l] <= numL && sums[l] > newSum) {
80+
count++;
81+
}
82+
modify(segment, prvSegIdx, sums[l] + newSum);
83+
}
84+
if (nextSegIdx != -1) {
85+
int r = rights[nextSegIdx];
86+
if (numR > sums[r] && newSum <= sums[r]) {
87+
count--;
88+
} else if (numR <= sums[r] && newSum > sums[r]) {
89+
count++;
90+
}
91+
modify(segment, nextSegIdx, newSum + sums[r]);
92+
lefts[nextSegIdx] = arrIdxL;
8693
}
87-
merge();
88-
return this;
94+
modify(segment, segIdx, Long.MAX_VALUE);
95+
res++;
8996
}
97+
return res;
9098
}
9199

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++;
100+
private void modify(long[] segment, int idx, long num) {
101+
if (segment[idx] == num) {
102+
return;
103+
}
104+
segment[idx] = num;
105+
while (idx != 0) {
106+
idx = (idx - 1) / 2;
107+
int l = 2 * idx + 1;
108+
int r = 2 * idx + 2;
109+
segment[idx] = Math.min(segment[l], segment[r]);
101110
}
102-
return res;
103111
}
104112
}

0 commit comments

Comments
 (0)