HDU 2689.求逆序(树状数组)

/*************************************

题目大意:给你1——n之间的数,组成的一串数;求出这组数的逆序数(所谓逆序就是比i小的数排在i的后面);

题目解析:运用树状数组动态的对上更新tree[ ] 数组,对下统计getsum[ ]数组,每更新一次都计算出getsum(n)-getsum(x) --------(此时的getsum(n)-getsum(x)表示的时x之前比x大的数的个数,它与逆序的定义相似),并合计所有做差的和;

错误分析:1.要先统计getsum(n)-getsum(x),再更新数据,计算出X之前比X大的数的个数;             

                    2.tree[ ]数组初始化应为0;此时的update(x,val),val=1;

                     3.tree[i]表示A[i-2^k+1]到A[i]的和,此时A[ ]数组初始化为0;getsum[ ]表示A[1]到A[i]的和;

**************************/

#include<cstdio>
#include<iostream>
#include<cstring>
#define MAX 1005
using namespace std;
int n,tree[MAX];
int lowbit(int x)

//分离出后面的1;(如3:十进制3&-3=1   二进制11&01=1 (以补码形式计算)       4:  十进制4&-4=4    二进制100&100=100)
{
    return x&-x;
}
void update(int x,int val)

//更新数据,数组tree[  ]对上更新;
{
    while(x<=n)
    {
      tree[x]+=val;
      x+=lowbit(x);
    }
}
int getsum(int x)

//统计前x个数的和,对下更新
{
    int sum=0;
    while(x>0)
    {
        sum+=tree[x];

        /*如x=13,二进制为1101 ,则经过lowbit (),可得1100,1000

        于是getsum[1101]=tree[1101]+tree[1100]+tree[1000]*/
        x-=lowbit(x);
    }
    return sum;
}
int main()
{
    int i,x;
    long long s;
    while(scanf("%d",&n)!=EOF)
    {
        memset(tree,0,sizeof(tree));
        s=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&x);
            s+=getsum(n)-getsum(x);

          //每输入一个数(即更新一次)则计算出它前面比它大的数;
            update(x,1);

         //更新数据
        }

        printf("%lld\n",s);
    }
   return 0;
}


你可能感兴趣的:(ACM,杭电,2689.求逆序)