#include <cstdio> #include <algorithm> #include <cstring> #define ll long long using namespace std; const int maxn=100005; ll ans; int data[maxn]; int n; struct node { int a,b; }s[maxn]; ll cmp(node p,node q) { if(p.a==q.a) return p.b<q.b; else return p.a<q.a; } void Merge(int l,int mid,int r) //合并 { int k=0,i=l,j=mid+1; int tar[maxn]; //临时数组用来暂时存储有序数列 while(i<=mid&&j<=r) //把两组有序数列a[l]...a[mid]和a[mid+1]...a[r]合并成一组有序数列tar[0]...tar[r-l+1] { if(data[i]<=data[j]) //把小的数字给数组tar[] tar[k++]=data[i++]; else { tar[k++]=data[j++]; ans+=mid-i+1; //关键点,在后一组里有最小的数字,说明前一组序列里剩下的数字都比这个数字大,而且前一组数列里的每个数字都在后一组数列的前面 } } while(i<=mid) tar[k++]=data[i++]; while(j<=r) tar[k++]=data[j++]; for(k=0,i=l;i<=r;) //把有序数列复制给data[l]..data[r],data[]值是改变的,变成有序的,保证合并上一层有序数列时满足条件 data[i++]=tar[k++]; } void MergeSort(int l,int r) //排序 { if(l<r) { int mid=(l+r)/2; MergeSort(l,mid); MergeSort(mid+1,r); Merge(l,mid,r); } } int main(void) { while(scanf("%d",&n)!=EOF) { memset(data,0,sizeof(data)); for (int i=0;i<n;i++) scanf("%d%d",&s[i].a,&s[i].b); sort(s,s+n,cmp); for(int i=0;i<n;i++) data[i]=s[i].b; ans=0; MergeSort(0,n-1); printf("%I64d\n",ans); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
ACM ICPC 2011–2012, NEERC, Northern Subregional Contest J. John’s Inversions(合并排序求逆序数对数)
原文地址:http://blog.csdn.net/criminalcode/article/details/48057659