poj2299_树状数组

题意:求逆序对。

分析:以前用分治的思想写的,这次用树状数组。

以array[]=9 1 0 5 4 为例,

1.对于每个array[i],求出小于等于array[i]的个数:

9:1

1:1

0:1

5:3

4:3个

这里如果遍历求的话,就超时了。因此需要构建树状数组,树状数组需要离散化。有:
array[] 9 1 0 5 4

num    1 2 3 4 5

这里不压缩要1--n内有时也行,如果数据小的话。

比如这个例子就行,离散到大于等于1就行。

但是如果数据大的话,就得压缩压下。

2.用树状数组求小于等于array[i]的个数应该以array[]由小到大排序遍历

i          1 2 3 4 5

array   0 1 4 5 9

num    3 2 5 4 1

array[]排序后也对应了num的一个顺序

依次对num进行更新,就可以tree[i]求出的就是小于等于array[i]的个数

3.用已经排序的对应的i-tree[i],即i-小于等于array[i]的个数的总和就是逆序数个数。

4.总结:关键是树状数组的构建,这里树状数组是用来求小于等于array[i]的个数的。

代码:

树状数组500ms

View Code
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <algorithm>
 4 #include <memory.h>
 5 using namespace std;
 6 //500ms
 7 const int maxnum=500000;
 8 struct node
 9 {
10     int digit;
11     int num;
12 }array[maxnum];
13 int tree[maxnum];
14 int n;
15 
16 bool cmp(struct node a,struct node b)
17 {
18     return a.digit<b.digit;
19 }
20 
21 void update(int index,int add)
22 {
23     while(index<=n)  //  1.是<=n
24     {
25         tree[index]+=add;
26         index+=((-index)&index);
27     }
28 }
29 
30 int getsum(int index)
31 {
32     int sum=0;
33     while(index>0)
34     {
35         sum+=tree[index];
36         index-=((-index)&index);
37     }
38     return sum;
39 }
40 
41 int main()
42 {
43     int i;
44     __int64 sum;
45     while(scanf("%d",&n) && n!=0)
46     {
47         for(i=1;i<=n;i++)
48         {
49             scanf("%d",&array[i].digit);
50             array[i].num=i;
51         }
52         sort(array+1,array+n+1,cmp);
53 
54         memset(tree,0,sizeof(tree)); //初始化树状数组
55         sum=0;
56         for(i=1;i<=n;i++)
57         {
58             update(array[i].num,1);
59             sum+=(i-getsum(array[i].num));
60         }
61         printf("%I64d\n",sum);
62     }
63     return 0;
64 }
65 
66 /*
67 5
68 9 1 0 5 4
69 */

分治1282ms

View Code
 1 #include <iostream>
 2 
 3 using namespace std;
 4 const int maxnum=1000000000;
 5 int a[500005];
 6 int larray[250005];
 7 int rarray[250005];
 8 long long cnt;   //这里是long long 否则wa
 9 
10 void Merge(int p,int q,int r)
11 {
12     int i;
13     int llen=q-p+1;
14     int rlen=r-q;
15     for(i=0;i<llen;i++)
16         larray[i]=a[p+i];
17     for(i=0;i<rlen;i++)
18         rarray[i]=a[q+1+i];
19     larray[llen]=maxnum;
20     rarray[rlen]=maxnum;
21 
22     int j,k;
23     i=0;j=0;
24     for(k=p;k<=r;k++)
25     {
26         if(larray[i]<=rarray[j])
27         {
28             a[k]=larray[i];
29             i++;
30         }
31         else
32         {
33             a[k]=rarray[j];
34             j++;
35             cnt+=llen-i;
36         }
37     }
38 }
39 
40 void Merge_Sort(int p,int r)
41 {
42     if(p<r)
43     {
44         int q=(p+r)/2;
45         Merge_Sort(p,q);
46         Merge_Sort(q+1,r);
47         Merge(p,q,r);
48     }
49 }
50 
51 int main()
52 {
53     int num,i;
54     while(cin>>num)
55     {
56         if(num==0) break;
57         for(i=0;i<num;i++)
58             cin>>a[i];
59         cnt=0;
60         Merge_Sort(0,num-1);
61         cout<<cnt<<endl;
62     }
63     return 0;
64 }

 

tjuoj 1455

posted @ 2012-08-17 09:37  pushing my way  阅读(218)  评论(0编辑  收藏  举报