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 }

 

posted @ 2012-08-18 19:00  pushing my way  阅读(312)  评论(0编辑  收藏  举报