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

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;

}

 

你可能感兴趣的:(树状数组)