Time limit per test: 4.0 seconds
Time limit all tests: 4.0 seconds
Memory limit: 256 megabytes
You want to process a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order.
Input
There are several test cases, please process till EOF
.
For each test case, the first line contains integer n (1≤n≤105) . The second line contains n space-separated integers a1,a2,…,an (1≤ai≤109) .
Output
For each test case, output the minimum times of swapping in one line.
Examples
2 1 2
0
题意: 求逆序对。
分析:
首先理解归并排序。 给你一个混乱的序列,先将它分半变成两个序列,分别对每个序列排序,然后合并两个序列。 合并的操作就是每次比较两个序列的最小值,然后将最小值放到新的序列中,并再原序列删除那个最小值。
具体操作就是不断二分,至到每个序列只包含一个元素,这样就可以默认当前元素已经排好序了,再进行合并即可。
那怎么求逆序对呢? 对于每个即将要合并两个序列,我们可以知道在两个序列的内部是不存在逆序对的(因为已经是排好序的)。所以逆序对只存在两个序列之间。举例来说
假设第一个序列为 3 4 5 第二个序列为 1 2
那么对与合并操作,肯定要先比较 3 和 1 的大小,然后将1放到新的序列中。 可以因为3比1大,所以这是一个逆序对,同样的,对于第一个序列中所有大于3的元素,每一个都可以和1构成逆序对,所以cnt每次要加所有大于等于3的元素的个数。
具体看代码。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<queue>
#include<iomanip>
using namespace std;
const int INF = 0x3f3f3f3f;
const int NINF = 0xc0c0c0c0;
const int maxn = 100005;
long long cnt = 0;
void merge_sort(int *A,int *T,int beg,int en)
{
if(en-beg>1){
int mid = beg + (en-beg)/2;
int s1 = beg,s2 = mid;
int e1 = mid,e2 = en;
int pos = beg;
merge_sort(A,T,s1,e1); //缩小问题规模
merge_sort(A,T,s2,e2);
while(s1<e1 && s2<e2){
if(A[s1] > A[s2]){
cnt += e1-s1; //只需要加一个cnt,即可求出逆序对的个数。
T[pos++] = A[s2++];
}
else T[pos++] = A[s1++];
}
while(s1 < e1){ //若出现一个序列为空,则将另一个序列的元素依次放入新的序列。
T[pos++] = A[s1++];
}
while(s2 < e2){
T[pos++] = A[s2++];
}
for(pos = beg;pos<en;pos++) //将每次合并好的序列放入原始序列(保证规模更大时,两个序列都是有序的)
A[pos] = T[pos];
}
}
int main()
{
int A[maxn]; //原始序列
int T[maxn]; //辅助序列
int n;
while(cin >> n){
memset(T,0,sizeof(T));
for(int i=0;i<n;i++){
cin >> A[i];
}
cnt = 0 ;
merge_sort(A,T,0,n);
cout << cnt << endl;
}
}