逆序数的分治法实现

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll M=500005;
ll q[M],b[M];
ll sum=0,p;//定义全局变量,用于计数;
void guibing(ll m,ll x,ll n)//归并,将两端数组合在一起;
{
    ll i=x+1,j=m,u=m;//定义初始值;
    while(j<=x&&i<=n)
    {
        if(q[j]<=q[i])
            b[u++]=q[i++];
        else
        {
            b[u++]=q[j++];
            sum+=n-i+1;//重点,默认从大到小排序
        }
    }
/*比如{4,3,2,1},{4,3,2,1}两个数组片段,比较开头的大小,如果后面的开头大于等于前面的,就可以先把其存起来,
只要小于了,就可以把sum加上此时的第二个片段剩余个数*/
    while(j<=x)
        b[u++]=q[j++];
    while(i<=n)
        b[u++]=q[i++];//如果没有存完,继续降序存入;
    for(ll i=m; i<u; i++)
    {
        q[i]=b[i];
    }//赋给q;
}
void guisort(ll m,ll n)//分治的递归实现;
{
    if(m==n)
        return ;
    ll x=(m+n)/2;
    guisort(m,x);
    guisort(x+1,n);
    guibing(m,x,n);
}
int main()
{
    ll p;
    while(scanf("%lld",&p)!=EOF&&p)
    {
        memset(q,0,sizeof(q));
        memset(b,0,sizeof(b));
        for(int i=0; i<p; i++)
            scanf("%lld",&q[i]);
        sum=0;
        guisort(0,p-1);
        printf("%lld\n",sum);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41081096/article/details/81391821