题意是给N张牌 每张牌上有两个不同颜色的数字 (有序) 求一种排列方式使同种颜色的数的逆序数对最少。
思路:
假设 对 逆序数对较多的颜色的牌排序,使得一种颜色的牌的逆序数达到最小,另一种颜色的数字会存在一些逆序数对。不存在更优的移动方式,使得另一种颜色减少的逆序数对大于已经有序的颜色增加的逆序数对。
实现:
用归并排序求逆序数对。
AC代码:
#include <bits/stdc++.h>
using namespace std;
struct node{
int red,blue;
}card[100005];
bool cmp1(node n1,node n2) {
if (n1.red==n2.red) return n1.blue<n2.blue;
else return n1.red<n2.red;
}
bool cmp2(node n1,node n2) {
if (n1.blue==n2.blue) return n1.red<n2.red;
else return n1.blue<n2.blue;
}
long long cnt1=0,cnt2=0;
int A[100005],T[100005];
void merge_sort(int x,int y) {
if (y-x>1) {
int m=x+(y-x)/2;
int p=x,q=m,i=x;
merge_sort(x,m);
merge_sort(m,y);
while (p<m||q<y){
if (q>=y||(p<m&&A[p]<=A[q])) T[i++]=A[p++];
else {
T[i++]=A[q++];
cnt1+=(m-p);
}
}
for (i=x;i<y;++i) A[i]=T[i];
}
}
void merge_sort2(int x,int y) {
if (y-x>1) {
int m=x+(y-x)/2;
int p=x,q=m,i=x;
merge_sort2(x,m);
merge_sort2(m,y);
while (p<m||q<y){
if (q>=y||(p<m&&A[p]<=A[q])) T[i++]=A[p++];
else {
T[i++]=A[q++];
cnt2+=(m-p);
}
}
for (i=x;i<y;++i) A[i]=T[i];
}
}
int main() {
//freopen("datain","r",stdin);
freopen("john.in","r",stdin);
freopen("john.out","w",stdout);
int n;
cin>>n;
for (int i=0;i<n;++i) scanf("%d %d",&card[i].red,&card[i].blue);
//first
sort(card,card+n,cmp1);
for (int i=0;i<n;++i) A[i]=card[i].blue;
//for (int i=0;i<n;++i) cout<<A[i]<<" ";
merge_sort(0,n);
//cout<<cnt1<<endl;
//second
sort(card,card+n,cmp2);
for (int i=0;i<n;++i) A[i]=card[i].red;
//for (int i=0;i<n;++i) cout<<A[i]<<" ";
merge_sort2(0,n);
//cout<<cnt2<<endl;
//for (int i=0;i<n;++i) cout<<A[i]<<" ";
cout<<min(cnt1,cnt2)<<endl;
return 0;
}