#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