数组中的逆序对 ——离散化+树状数组

http://ac.jobdu.com/problem.php?cid=1039&pid=19

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

先离散化 

在统计后面比前面大的有几个保存到all

逆序对队 n*(n-1)/2-all 注意long long

View Code
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

long long N;
long long tree[200009];

struct data
{
    long long no;
    long long real;
    long long pai;
}ss[200009];

long long lowbit(long long x)
{
    return x&(-x);
}

void updata(long long x,long long c)
{
    long long i;
    for(i=x;i<=N;i+=lowbit(i))
    {
        tree[i]+=c;
    }
}

long long getsum(long long x)
{
    long long i;
    long long temp=0;
    for(i=x;i>=1;i-=lowbit(i))
    {
        temp+=tree[i];
    }
    return temp;
}

long long cmp(data a,data b)
{
    if(a.real==b.real)
        return a.no<b.no;
    return a.real<b.real;
}

long long cmp2(data a,data b)
{
    return a.no<b.no;
}

int main()
{
    long long n;
    while(scanf("%lld",&n)!=EOF){
        N=n;
        long long i,j;
        for(i=1;i<=n;i++){
            scanf("%lld",&ss[i].real);
            ss[i].no=i;
        }

        sort(&ss[1],&ss[1+n],cmp);
        long long add=1;
        ss[1].pai=1;
        for(i=2;i<=n;i++){
            if(ss[i].real==ss[i-1].real)
                ss[i].pai=ss[i-1].pai;
            else
                ss[i].pai=ss[i-1].pai+1;
        }
        sort(&ss[1],&ss[1+n],cmp2);
        //for(i=1;i<=n;i++){
        //    printf("%d ",ss[i].pai);
        //}

        for(i=0;i<=n;i++)
        {
            tree[i]=0;
        }

        long long all=0;
        updata(ss[1].pai,1);
        for(i=2;i<=n;i++)
        {
            all+=getsum(ss[i].pai);
            updata(ss[i].pai,1);
        }

        long long temp=n*(n-1)/2-all;
        printf("%lld\n",temp);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/huhuuu/p/2857580.html