Codeforces 1375 E. Inversion SwapSort(逆序對)

Madeline has an array 𝑎 of 𝑛 integers. A pair (𝑢,𝑣) of integers forms an inversion in 𝑎 if:

1≤𝑢<𝑣≤𝑛.
𝑎𝑢>𝑎𝑣.
Madeline recently found a magical paper, which allows her to write two indices 𝑢 and 𝑣 and swap the values 𝑎𝑢 and 𝑎𝑣. Being bored, she decided to write a list of pairs (𝑢𝑖,𝑣𝑖) with the following conditions:

all the pairs in the list are distinct and form an inversion in 𝑎.
all the pairs that form an inversion in 𝑎 are in the list.
Starting from the given array, if you swap the values at indices 𝑢1 and 𝑣1, then the values at indices 𝑢2 and 𝑣2 and so on, then after all pairs are processed, the array 𝑎 will be sorted in non-decreasing order.
Construct such a list or determine that no such list exists. If there are multiple possible answers, you may find any of them.

Input
The first line of the input contains a single integer 𝑛 (1≤𝑛≤1000) — the length of the array.

Next line contains 𝑛 integers 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤109) — elements of the array.

Output
Print -1 if no such list exists. Otherwise in the first line you should print a single integer 𝑚 (0≤𝑚≤𝑛(𝑛−1)2) — number of pairs in the list.

The 𝑖-th of the following 𝑚 lines should contain two integers 𝑢𝑖,𝑣𝑖 (1≤𝑢𝑖<𝑣𝑖≤𝑛).

If there are multiple possible answers, you may find any of them.

Examples
inputCopy
3
3 1 2
outputCopy
2
1 3
1 2
inputCopy
4
1 8 1 6
outputCopy
2
2 4
2 3
inputCopy
5
1 1 1 2 2
outputCopy
0
Note
In the first sample test case the array will change in this order [3,1,2]→[2,1,3]→[1,2,3].

In the second sample test case it will be [1,8,1,6]→[1,6,1,8]→[1,1,6,8].

In the third sample test case the array is already sorted.

題意:
給逆序對排個序,使得按照這些數對進行交換後序列逆序數爲0

思路:
感覺很迷,沒想通。。。
瞎說一下,感覺想通了,但不是正解

有三個排序判斷標準:

  1. 先排結尾數字大的
  2. 後排結尾座標大的
  3. 再排開頭座標小的

首先對於同一個數字的所有逆序對,結尾數字肯定相同,結尾座標肯定相同,那麼此時你把這些逆序對按開頭座標排序然後交換完,結果是最後一個數字移到最前面,其他數字不變。

如 2 3 1
逆序對爲 (1 3) (2 3),則移動完了以後,爲 1 2 3,只是把1移到了2 3後面。

那麼對於相同數字不同結尾座標的,先移動結尾座標大的。因爲前面的數字有的逆序對,後面的數字一定也有。所以這樣一定相當於先把後面的數字移到前面來,再把這些數字一個一個往前挪。

如 2 1 2 1,
逆序對爲 (1 2) (3 4) (1,4)
先移動(3,4),之後爲 2 1 1 2,
再移動(1,2) (1,4),結果爲1 1 2 2

最後就是先考慮數字大結尾的逆序對,這樣做的結果不會影響數字小結尾的逆序對。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#include <queue>
#include <map>
#include <string>
#include <iostream>
#include <cmath>

using namespace std;
typedef long long ll;

const int maxn = 1000 + 7;

int a[maxn];

int cmp(pair<int,int>a1,pair<int,int>a2) {
    if(a[a1.second] == a[a2.second]) {
        if(a1.second == a2.second) {
            return a1.first < a2.first;
        }
        return a1.second > a2.second;
    }
    return a[a1.second] > a[a2.second];
}

int main() {
    vector<pair<int,int> >vec;
    int n;scanf("%d",&n);
    for(int i = 1;i <= n;i++) {
        scanf("%d",&a[i]);
    }
    for(int i = 1;i <= n;i++) {
        for(int j = i + 1;j <= n;j++) {
            if(a[i] > a[j]) {
                vec.push_back({i,j});
            }
        }
    }
    
    sort(vec.begin(),vec.end(),cmp);
    
    printf("%d\n",vec.size());
    for(int i = 0;i < vec.size();i++) {
        printf("%d %d\n",vec[i].first,vec[i].second);
    }
    
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章