Frosh Week
时间限制: 1S类别: 枚举和贪心->中等
问题描述 :
During Frosh Week, students play various fun games to get to know each other and compete against other teams. In one such game, all the frosh on a team stand in a line, and are then asked to arrange themselves according to some criterion, such as their height, their birth date, or their student number. This rearrangement of the line must be accomplished only by successively swapping pairs of consecutive students. The team that finishes fastest wins. Thus, in order to win, you would like to minimize the number of swaps required.
输入说明 :
The first line of input contains one positive integer n, the number of students on the team, which will be no more than one million. The following n lines each contain one integer, the student number of each student on the team. No student number will appear more than once.
输出说明 :
Output a line containing the minimum number of swaps required to arrange the students in increasing order by student number.
输入范例 :
20
824999217
22573102
984397395
215416235
247826578
910725073
941794862
173672226
419559552
719826673
141666075
82167875
444979293
319136227
351013707
904455923
398197417
94379523
759276975
50151619
输出范例 :
108
思路:
本质上即求数组的逆序对个数,第一反应想到冒泡,但是冒泡复杂度O(n^2),再看这题数据量100万,显然会超时
那可以想到,将大问题分解成小问题,求出小块的逆序对数再相加,即可算出总块的逆序对,用归并排序可以实现,时间复杂度为O(nlogn)
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<iomanip>
#include<vector>
#include<string>
#include<set>
#include<utility>
using namespace std;
//求逆序数
int n;
int mergeSort(int a[], int l, int r) {//即求区间[l,r]之间有多少个逆序对
//[l,r]之间的逆序对可分为 1.[l,mid]的逆序对 2.[mid+1,r]的逆序对 3.横跨两个区间的逆序对
int mid = (l + r) / 2;
if (l >= r)
return 0;//区间中包含一个或者没有元素,显然逆序对为0
int* tmp = new int[n + 5];
int pos = l;
int cnt = mergeSort(a, l, mid) + mergeSort(a, mid + 1, r);//求出1. 2. 的逆序对数
//求3. 的逆序对数
int i = l, j = mid + 1;
while (i <= mid && j <= r) {
if (a[i] <= a[j]) {
tmp[pos] = a[i];
i++;
pos++;
}
else {
tmp[pos] = a[j];
j++;
pos++;
cnt += (mid - i + 1);
}
}
//剩下元素加入
for (i; i <= mid; i++) {
tmp[pos] = a[i];
pos++;
}
for (j; j <= r; j++) {
tmp[pos] = a[j];
pos++;
}
//修改为(部分)排序后的数组
for (int m = l; m <= r; m++)
a[m] = tmp[m];
return cnt;
}
int main()
{
cin >> n;
int* a = new int[n + 5];
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int res = mergeSort(a, 0, n - 1);
cout << res << endl;
return 0;
}