Skip to content

Commit 0b892d3

Browse files
committed
Improved task 3510
1 parent 39b42c1 commit 0b892d3

File tree

1 file changed

+87
-279
lines changed
  • src/main/java/g3501_3600/s3510_minimum_pair_removal_to_sort_array_ii

1 file changed

+87
-279
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,296 +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_492_ms_(98.32%)_Space_62.71_MB_(97.48%)
4+
// #Doubly_Linked_List #2025_04_09_Time_289_ms_(99.58%)_Space_82.88_MB_(17.23%)
55

6-
import java.util.ArrayList;
7-
import java.util.Arrays;
8-
import java.util.List;
9-
10-
@SuppressWarnings("java:S127")
116
public class Solution {
12-
public int minimumPairRemoval(int[] nums) {
13-
int n = nums.length;
14-
LST lst = new LST(n);
15-
lst.setRange(n);
16-
int dec = 0;
17-
long[] a = new long[nums.length];
18-
for (int i = 0; i < n; i++) {
19-
a[i] = nums[i];
20-
}
21-
for (int i = 0; i < n - 1; i++) {
22-
if (a[i] > a[i + 1]) {
23-
dec++;
24-
}
25-
}
26-
MinHeapL h = new MinHeapL(n);
27-
for (int i = 0; i < n - 1; i++) {
28-
h.add(i, (a[i + 1] + a[i]), i);
29-
}
30-
int step = 0;
31-
while (dec > 0) {
32-
step++;
33-
int arg = h.argmin();
34-
h.remove(arg);
35-
int r = lst.next(arg + 1);
36-
assert r != -1;
37-
h.remove(r);
38-
int ll = lst.prev(arg - 1);
39-
int rr = lst.next(r + 1);
40-
if (a[arg] > a[r]) {
41-
dec--;
42-
}
43-
if (ll >= 0 && a[ll] > a[arg]) {
44-
dec--;
45-
}
46-
if (rr != -1 && a[r] > a[rr]) {
47-
dec--;
48-
}
49-
a[arg] += a[r];
50-
a[r] = 0;
51-
lst.unset(r);
52-
if (ll >= 0) {
53-
if (a[ll] > a[arg]) {
54-
dec++;
55-
}
56-
h.update(ll, (a[ll] + a[arg]), ll);
57-
}
58-
if (rr != -1) {
59-
if (a[arg] > a[rr]) {
60-
dec++;
61-
}
62-
h.update(arg, (a[arg] + a[rr]), arg);
63-
}
64-
}
65-
return step;
66-
}
67-
68-
public static class MinHeapL {
69-
static final long INF = Long.MAX_VALUE;
70-
71-
long[] hi;
72-
long[] lo;
73-
int[] map;
74-
int[] imap;
75-
int n;
76-
int pos;
77-
78-
public MinHeapL(int m) {
79-
n = Integer.highestOneBit((m + 1) << 1);
80-
hi = new long[n];
81-
lo = new long[n];
82-
map = new int[n];
83-
imap = new int[n];
84-
Arrays.fill(hi, INF);
85-
Arrays.fill(lo, INF);
86-
Arrays.fill(map, -1);
87-
Arrays.fill(imap, -1);
88-
pos = 1;
89-
}
90-
91-
public void add(int ind, long hiValue, long loValue) {
92-
if (imap[ind] < 0) {
93-
hi[pos] = hiValue;
94-
lo[pos] = loValue;
95-
map[pos] = ind;
96-
imap[ind] = pos;
97-
pos++;
98-
up(pos - 1);
99-
}
100-
}
101-
102-
public void update(int ind, long hiValue, long loValue) {
103-
if (imap[ind] < 0) {
104-
hi[pos] = hiValue;
105-
lo[pos] = loValue;
106-
map[pos] = ind;
107-
imap[ind] = pos;
108-
pos++;
109-
up(pos - 1);
110-
} else {
111-
int p = imap[ind];
112-
hi[p] = hiValue;
113-
lo[p] = loValue;
114-
up(p);
115-
down(p);
116-
}
117-
}
118-
119-
public long remove(int ind) {
120-
if (pos == 1) {
121-
return INF;
122-
}
123-
if (imap[ind] == -1) {
124-
return INF;
125-
}
126-
int rem = imap[ind];
127-
long ret = hi[rem];
128-
pos--;
129-
hi[rem] = hi[pos];
130-
lo[rem] = lo[pos];
131-
int movedInd = map[pos];
132-
map[rem] = movedInd;
133-
imap[movedInd] = rem;
134-
hi[pos] = INF;
135-
lo[pos] = INF;
136-
map[pos] = -1;
137-
imap[ind] = -1;
138-
up(rem);
139-
down(rem);
140-
return ret;
141-
}
142-
143-
public long min() {
144-
return hi[1];
145-
}
146-
147-
public int argmin() {
148-
return map[1];
149-
}
150-
151-
public int size() {
152-
return pos - 1;
153-
}
154-
155-
public long get(int ind) {
156-
return hi[imap[ind]];
157-
}
158-
159-
private void up(int cur) {
160-
for (int c = cur, p = c >>> 1; p >= 1; c = p, p = c >>> 1) {
161-
if (compare(p, c) > 0) {
162-
swap(p, c);
7+
private static class Segment {
8+
private int start;
9+
private 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;
20+
21+
public static Segment init(int[] arr) {
22+
return new Segment(arr, 0, arr.length - 1);
23+
}
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;
34+
}
35+
int mid = s + ((e - s) >> 1);
36+
left = new Segment(arr, s, mid);
37+
right = new Segment(arr, mid + 1, e);
38+
merge();
39+
}
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+
}
60+
}
61+
62+
public void update(int i, long n) {
63+
if (start <= i && end >= i) {
64+
if (start >= end) {
65+
lNum = rNum = n;
16366
} else {
164-
break;
67+
left.update(i, n);
68+
right.update(i, n);
69+
merge();
16570
}
16671
}
16772
}
16873

169-
private void down(int cur) {
170-
for (int c = cur; 2 * c < pos; ) {
171-
int child = 2 * c;
172-
if (child + 1 < pos && compare(child, child + 1) > 0) {
173-
child++;
174-
}
175-
if (compare(c, child) > 0) {
176-
swap(c, child);
177-
c = child;
178-
} else {
179-
break;
180-
}
74+
public Segment remove(int i) {
75+
if (start > i || end < i) {
76+
return this;
77+
} else if (start >= end) {
78+
return null;
18179
}
182-
}
183-
184-
private int compare(int i, int j) {
185-
if (hi[i] != hi[j]) {
186-
return Long.compare(hi[i], hi[j]);
187-
} else {
188-
return Long.compare(lo[i], lo[j]);
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;
18986
}
190-
}
191-
192-
private void swap(int i, int j) {
193-
long tmpHi = hi[i];
194-
hi[i] = hi[j];
195-
hi[j] = tmpHi;
196-
long tmpLo = lo[i];
197-
lo[i] = lo[j];
198-
lo[j] = tmpLo;
199-
int tmpMap = map[i];
200-
map[i] = map[j];
201-
map[j] = tmpMap;
202-
imap[map[i]] = i;
203-
imap[map[j]] = j;
87+
merge();
88+
return this;
20489
}
20590
}
20691

207-
private static class LST {
208-
long[][] set;
209-
int n;
210-
211-
public LST(int n) {
212-
this.n = n;
213-
int d = 1;
214-
for (int m = n; m > 1; m >>>= 6, d++) {}
215-
216-
set = new long[d][];
217-
for (int i = 0, m = n >>> 6; i < d; i++, m >>>= 6) {
218-
set[i] = new long[m + 1];
219-
}
220-
}
221-
222-
public void setRange(int r) {
223-
for (int i = 0; i < set.length; i++, r = r + 63 >>> 6) {
224-
for (int j = 0; j < r >>> 6; j++) {
225-
set[i][j] = -1L;
226-
}
227-
if ((r & 63) != 0) {
228-
set[i][r >>> 6] |= (1L << r) - 1;
229-
}
230-
}
231-
}
232-
233-
public void unset(int pos) {
234-
if (pos >= 0 && pos < n) {
235-
for (int i = 0;
236-
i < set.length && (i == 0 || set[i - 1][pos] == 0L);
237-
i++, pos >>>= 6) {
238-
set[i][pos >>> 6] &= ~(1L << pos);
239-
}
240-
}
241-
}
242-
243-
public int prev(int pos) {
244-
for (int i = 0; i < set.length && pos >= 0; i++, pos >>>= 6, pos--) {
245-
int pre = prevValue(set[i][pos >>> 6], pos & 63);
246-
if (pre != -1) {
247-
pos = pos >>> 6 << 6 | pre;
248-
while (i > 0) {
249-
pos = pos << 6 | 63 - Long.numberOfLeadingZeros(set[--i][pos]);
250-
}
251-
return pos;
252-
}
253-
}
254-
return -1;
255-
}
256-
257-
public int next(int pos) {
258-
for (int i = 0; i < set.length && pos >>> 6 < set[i].length; i++, pos >>>= 6, pos++) {
259-
int nex = nextValue(set[i][pos >>> 6], pos & 63);
260-
if (nex != -1) {
261-
pos = pos >>> 6 << 6 | nex;
262-
while (i > 0) {
263-
pos = pos << 6 | Long.numberOfTrailingZeros(set[--i][pos]);
264-
}
265-
return pos;
266-
}
267-
}
268-
return -1;
269-
}
270-
271-
private int prevValue(long set, int n) {
272-
long h = set << ~n;
273-
if (h == 0L) {
274-
return -1;
275-
}
276-
return -Long.numberOfLeadingZeros(h) + n;
277-
}
278-
279-
private int nextValue(long set, int n) {
280-
long h = set >>> n;
281-
if (h == 0L) {
282-
return -1;
283-
}
284-
return Long.numberOfTrailingZeros(h) + n;
285-
}
286-
287-
@Override
288-
public String toString() {
289-
List<Integer> list = new ArrayList<>();
290-
for (int pos = next(0); pos != -1; pos = next(pos + 1)) {
291-
list.add(pos);
292-
}
293-
return list.toString();
294-
}
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++;
101+
}
102+
return res;
295103
}
296104
}

0 commit comments

Comments
 (0)