@@ -82,32 +82,287 @@ tags:
8282
8383<!-- solution:start -->
8484
85- ### 方法一
85+ ### 方法一:有序集合
86+
87+ 我们定义一个有序集合 $\textit{sl}$ 来存储所有相邻元素对的和及其左侧下标的元组 $(\textit{s}, i)$,定义另一个有序集合 $\textit{idx}$ 来存储当前数组中剩余元素的下标,并使用变量 $\textit{inv}$ 来记录当前数组中的逆序对数量。初始时,我们遍历数组 $\textit{nums}$,将所有相邻元素对的和及其左侧下标的元组加入有序集合 $\textit{sl}$ 中,并计算逆序对数量 $\textit{inv}$。
88+
89+ 在每次操作中,我们从有序集合 $\textit{sl}$ 中取出和最小的元素对 $(\textit{s}, i)$,那么我们可以得到下标 $i$ 和 $j$(其中 $j$ 是下标 $i$ 在有序集合 $\textit{idx}$ 中的下一个下标)对应的元素对是当前数组中和最小的相邻元素对。如果 $nums[ i] > nums[ j] $,则说明该元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 减一。
90+
91+ 接下来,我们需要更新与下标 $i$ 和 $j$ 相关的元素对:
92+
93+ 1 . 如果下标 $i$ 在有序集合 $\textit{idx}$ 中有前驱下标 $h$,则需要更新元素对 $(h, i)$。如果 $nums[ h] > nums[ i] $,则说明该元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 减一。然后,我们从有序集合 $\textit{sl}$ 中移除元素对 $(h, i)$,并将新的元素对 $(h, s)$ 加入有序集合 $\textit{sl}$ 中。如果 $nums[ h] > s$,则说明新的元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 加一。
94+
95+ 2 . 如果下标 $j$ 在有序集合 $\textit{idx}$ 中有后继下标 $k$,则需要更新元素对 $(j, k)$。如果 $nums[ j] > nums[ k] $,则说明该元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 减一。然后,我们从有序集合 $\textit{sl}$ 中移除元素对 $(j, k)$,并将新的元素对 $(s, k)$ 加入有序集合 $\textit{sl}$ 中。如果 $s > nums[ k] $,则说明新的元素对是一个逆序对,合并替换后逆序对数量 $\textit{inv}$ 加一。
96+
97+ 接下来,我们将下标 $i$ 处的元素替换为 $\textit{s}$,并从有序集合 $\textit{idx}$ 中移除下标 $j$。我们重复上述过程,直到逆序对数量 $\textit{inv}$ 为零为止。最终,操作次数即为将数组变为非递减所需的最小操作次数。
98+
99+ 时间复杂度 $O(n \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度。
86100
87101<!-- tabs:start -->
88102
89103#### Python3
90104
91105``` python
92-
106+ class Solution :
107+ def minimumPairRemoval (self , nums : List[int ]) -> int :
108+ n = len (nums)
109+ sl = SortedList()
110+ idx = SortedList(range (n))
111+ inv = 0
112+ for i in range (n - 1 ):
113+ sl.add((nums[i] + nums[i + 1 ], i))
114+ if nums[i] > nums[i + 1 ]:
115+ inv += 1
116+ ans = 0
117+ while inv:
118+ ans += 1
119+ s, i = sl.pop(0 )
120+ pos = idx.index(i)
121+ j = idx[pos + 1 ]
122+ if nums[i] > nums[j]:
123+ inv -= 1
124+ if pos > 0 :
125+ h = idx[pos - 1 ]
126+ if nums[h] > nums[i]:
127+ inv -= 1
128+ sl.remove((nums[h] + nums[i], h))
129+ if nums[h] > s:
130+ inv += 1
131+ sl.add((nums[h] + s, h))
132+ if pos + 2 < len (idx):
133+ k = idx[pos + 2 ]
134+ if nums[j] > nums[k]:
135+ inv -= 1
136+ sl.remove((nums[j] + nums[k], j))
137+ if s > nums[k]:
138+ inv += 1
139+ sl.add((s + nums[k], i))
140+
141+ nums[i] = s
142+ idx.remove(j)
143+ return ans
93144```
94145
95146#### Java
96147
97148``` java
98-
149+ class Solution {
150+ record Pair (long s , int i ) implements Comparable<Pair > {
151+ @Override
152+ public int compareTo(Pair other) {
153+ int compareS = Long . compare(this . s, other. s);
154+ return compareS != 0 ? compareS : Integer . compare(this . i, other. i);
155+ }
156+ }
157+
158+ public int minimumPairRemoval (int [] nums ) {
159+ int n = nums. length;
160+ int inv = 0 ;
161+ TreeSet<Pair > sl = new TreeSet<> ();
162+ for (int i = 0 ; i < n - 1 ; ++ i) {
163+ if (nums[i] > nums[i + 1 ]) {
164+ ++ inv;
165+ }
166+ sl. add(new Pair (nums[i] + nums[i + 1 ], i));
167+ }
168+ TreeSet<Integer > idx = new TreeSet<> ();
169+ long [] arr = new long [n];
170+ for (int i = 0 ; i < n; ++ i) {
171+ idx. add(i);
172+ arr[i] = nums[i];
173+ }
174+
175+ int ans = 0 ;
176+ while (inv > 0 ) {
177+ ++ ans;
178+ var p = sl. pollFirst();
179+ long s = p. s;
180+ int i = p. i;
181+ int j = idx. higher(i);
182+ if (arr[i] > arr[j]) {
183+ -- inv;
184+ }
185+ Integer h = idx. lower(i);
186+ if (h != null ) {
187+ if (arr[h] > arr[i]) {
188+ -- inv;
189+ }
190+ sl. remove(new Pair (arr[h] + arr[i], h));
191+ if (arr[h] > s) {
192+ ++ inv;
193+ }
194+ sl. add(new Pair (arr[h] + s, h));
195+ }
196+ Integer k = idx. higher(j);
197+ if (k != null ) {
198+ if (arr[j] > arr[k]) {
199+ -- inv;
200+ }
201+ sl. remove(new Pair (arr[j] + arr[k], j));
202+ if (s > arr[k]) {
203+ ++ inv;
204+ }
205+ sl. add(new Pair (s + arr[k], i));
206+ }
207+ arr[i] = s;
208+ idx. remove(j);
209+ }
210+ return ans;
211+ }
212+ }
99213```
100214
101215#### C++
102216
103217``` cpp
104-
218+ class Solution {
219+ public:
220+ int minimumPairRemoval(vector<int >& nums) {
221+ int n = nums.size();
222+ int inv = 0;
223+
224+ set<pair<long long, int>> sl;
225+ set<int> idx;
226+ vector<long long> arr(nums.begin(), nums.end());
227+
228+ for (int i = 0; i < n; ++i) idx.insert(i);
229+
230+ for (int i = 0; i < n - 1; ++i) {
231+ if (nums[i] > nums[i + 1]) {
232+ ++inv;
233+ }
234+ sl.insert({(long long) nums[ i] + nums[ i + 1] , i});
235+ }
236+
237+ int ans = 0;
238+ while (inv > 0) {
239+ ++ans;
240+
241+ auto it = sl.begin();
242+ long long s = it->first;
243+ int i = it->second;
244+ sl.erase(it);
245+
246+ auto j_it = idx.upper_bound(i);
247+ int j = *j_it;
248+
249+ if (arr[i] > arr[j]) {
250+ --inv;
251+ }
252+
253+ auto i_it = idx.find(i);
254+ if (i_it != idx.begin()) {
255+ auto h_it = prev(i_it);
256+ int h = *h_it;
257+
258+ if (arr[h] > arr[i]) {
259+ --inv;
260+ }
261+ sl.erase({arr[h] + arr[i], h});
262+
263+ if (arr[h] > s) {
264+ ++inv;
265+ }
266+ sl.insert({arr[h] + s, h});
267+ }
268+
269+ auto k_it = next(j_it);
270+ if (k_it != idx.end()) {
271+ int k = *k_it;
272+
273+ if (arr[j] > arr[k]) {
274+ --inv;
275+ }
276+ sl.erase({arr[j] + arr[k], j});
277+
278+ if (s > arr[k]) {
279+ ++inv;
280+ }
281+ sl.insert({s + arr[k], i});
282+ }
283+
284+ arr[i] = s;
285+ idx.erase(j);
286+ }
287+
288+ return ans;
289+ }
290+ };
105291```
106292
107293#### Go
108294
109295``` go
110-
296+ func minimumPairRemoval (nums []int ) (ans int ) {
297+ type pair struct { s, i int }
298+
299+ n := len (nums)
300+ inv := 0
301+
302+ sl := redblacktree.NewWith [pair, struct {}](func (a, b pair) int { return cmp.Or (a.s -b.s , a.i -b.i ) })
303+ idx := redblacktree.New [int , struct {}]()
304+ for i := 0 ; i < n; i++ {
305+ idx.Put (i, struct {}{})
306+ }
307+
308+ for i := 0 ; i < n-1 ; i++ {
309+ if nums[i] > nums[i+1 ] {
310+ inv++
311+ }
312+ sl.Put (pair{nums[i] + nums[i+1 ], i}, struct {}{})
313+ }
314+
315+ for inv > 0 {
316+ ans++
317+
318+ it := sl.Iterator ()
319+ it.First ()
320+ p := it.Key ()
321+ sl.Remove (p)
322+
323+ s , i := p.s , p.i
324+
325+ jNode , _ := idx.Ceiling (i + 1 )
326+ j := jNode.Key
327+
328+ if nums[i] > nums[j] {
329+ inv--
330+ }
331+
332+ if hNode , ok := idx.Floor (i - 1 ); ok {
333+ h := hNode.Key
334+
335+ if nums[h] > nums[i] {
336+ inv--
337+ }
338+ sl.Remove (pair{nums[h] + nums[i], h})
339+
340+ if nums[h] > s {
341+ inv++
342+ }
343+ sl.Put (pair{nums[h] + s, h}, struct {}{})
344+ }
345+
346+ if kNode , ok := idx.Ceiling (j + 1 ); ok {
347+ k := kNode.Key
348+
349+ if nums[j] > nums[k] {
350+ inv--
351+ }
352+ sl.Remove (pair{nums[j] + nums[k], j})
353+
354+ if s > nums[k] {
355+ inv++
356+ }
357+ sl.Put (pair{s + nums[k], i}, struct {}{})
358+ }
359+
360+ nums[i] = s
361+ idx.Remove (j)
362+ }
363+
364+ return
365+ }
111366```
112367
113368<!-- tabs:end -->
0 commit comments