归并排序---求逆序对

引例--超级贞鱼(http://oi.nks.edu.cn/zh/Problem/Details?cid=496&tid=F)(https://www.lydsy.com/JudgeOnline/problem.php?id=4769

超级贞鱼

超级贞鱼
时间限制 : - MS   空间限制 : - KB 
评测说明 : 1s,128m
问题描述

马达加斯加贞鱼是一种神奇的双脚贞鱼,它们把自己的智慧写在脚上——每只贞鱼的左脚和右脚上个有一个数。
有一天,K只贞鱼兴致来潮( 1<=k<=20^5),排成一列,从左到右第i只贞鱼会在右脚写Ai(1<=Ai<=10^9 ),左脚上写上i(1≤i≤K),
第二年,这K只贞鱼按右脚的数从小到大排成一列,然后,它们决定重编号,从左到右第i只贞鱼会在右脚上写上左脚的数,在左脚上写i,
第三年,它们按第二年的方法重排列、重编号......n年后( 1<=n<=10^5),对于从左到右第i和第j贞鱼,若i<j且第i只贞鱼右脚上的数比第j只贞鱼右脚上的数大,则称它们为一对“超级贞鱼”。
问一共有多少对“超级贞鱼”。

输入格式

一共3行,第一行一个正整数k(),
第二行k个数从左到右输入Ai( ),
第三行一个正整数n( )。

输出格式

一个整数,表示“超级贞鱼”对数。

样例输入

6
5 2 6 3 1 7
0

样例输出

7

提示

对于全部数据: Ai<=10^9。
30%的数据:n,k<=400;
70%的数据:n,k<=10000;
100%的数据:n,k<=200000;

直接求Ai逆序对

满分最快代码模板

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
    char ch=nc();int sum=0;
    while(!(ch>='0'&&ch<='9'))ch=nc();
    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
    return sum;
}
int n,v[2000010],p[2000010];
ll ans;
void solve(int l,int r)
{
    if(l==r)    return ;
    int mid=(l+r)>>1,i=l,h1=l,h2=mid+1;
    solve(l,mid),solve(mid+1,r);
    for(i=l;i<=r;i++)
    {
        if(h1<=mid&&(h2>r||v[h1]<=v[h2]))  ans+=h2-mid-1,p[i]=v[h1++];
        else    p[i]=v[h2++];
    }
    for(i=l;i<=r;i++)    v[i]=p[i];
}
int main()
{
    n=rd();
    int i;
    for(i=1;i<=n;i++)    v[i]=rd();
    solve(1,n);
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/CXYscxy/p/11352354.html