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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章