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