poj2299_树状数组II

这个题做过了,今天是树状数组的另一个版本。

分析:

例如 9 1 0 5 4

一般数据小的话,我们求每个数字前面小于等于它的个数,只需要离散到大于等于1的范围内。

9: update(10),sum(10) --->1

1:   update(2),sum(2)--->1

0:   update(1),sum(0)--->1

5:   update(6),sum(6)--->3

4:   update(5),sum(5)--->3

但是这个题数据范围很大,因此必须得压缩一下

注意到 9在序列中第5大,1第2大,。。。。

因此,将 9 1 0 5 4替换成5 2 1 4 3做树状数组是不变的

然后对应的5-1;2-1;1-1;4-3;3-3;求和就可得逆序数。

代码:

View Code
 1 #include <iostream>

 2 #include <stdio.h>

 3 #include <algorithm>

 4 #include <memory.h>

 5 using namespace std;

 6 const int maxnum=500000;

 7 struct node

 8 {

 9     int digit;

10     int num;

11 }array[maxnum],temp[maxnum];

12 int tree[maxnum];

13 int n;

14 

15 bool cmp(struct node a,struct node b)

16 {

17     return a.digit<b.digit;

18 }

19 

20 void update(int index,int add)

21 {

22     while(index<=n)  //  1.是<=n

23     {

24         tree[index]+=add;

25         index+=((-index)&index);

26     }

27 }

28 

29 int getsum(int index)

30 {

31     int sum=0;

32     while(index>0)

33     {

34         sum+=tree[index];

35         index-=((-index)&index);

36     }

37     return sum;

38 }

39 

40 

41 int main()

42 {

43     int i;

44     long long sum;

45     while(scanf("%d",&n) && n!=0)

46     {

47         for(i=1;i<=n;i++)

48         {

49             scanf("%d",&array[i].digit);

50             temp[i].digit=array[i].digit;

51             temp[i].num=i;

52         }

53         sort(temp+1,temp+n+1,cmp);

54         for(i=1;i<=n;i++)

55             array[temp[i].num].num=i;

56         memset(tree,0,sizeof(tree)); //初始化树状数组

57         sum=0;

58         for(i=1;i<=n;i++)

59         {

60             update(array[i].num,1);

61             sum+=(array[i].num-getsum(array[i].num));

62         }

63         printf("%I64d\n",sum);

64         //cout<<sum<<endl;

65     }

66     return 0;

67 }

 

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