Poj--2299(树状数组 or 归并排序,逆序数)
2014-09-08 16:47:48
思路:很久以前写了个归并排序,贴在这方便以后看吧。现在在练树状数组,通过这题顺便学了离散化,来说说吧:通过离散化保存下数的相对大小,然后用树状数组求出每个数前面有多少个数比它小,然后根据这个数的位置就能求出前面有多少个数比它大了(即逆序数)。
树状数组版:
1 /************************************************************************* 2 > File Name: p2299.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Mon 08 Sep 2014 04:08:46 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <queue> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 typedef long long ll; 18 const int INF = 1 << 29; 19 const int maxn = 500005; 20 21 struct node{ 22 int val,pos; 23 }no[maxn]; 24 25 int c[maxn],n,ref[maxn]; 26 27 int Lowbit(int x){return x & (-x);} 28 void Update(int x,int d){while(x <= maxn){c[x] += d,x += Lowbit(x);}} 29 int Getsum(int x){int res = 0;while(x){res += c[x],x -= Lowbit(x);}return res;} 30 31 bool cmp(node a,node b){ 32 return a.val < b.val; 33 } 34 35 int main(){ 36 while(scanf("%d",&n) != EOF && n){ 37 memset(c,0,sizeof(c)); 38 for(int i = 1; i <= n; ++i){ 39 scanf("%d",&no[i].val); 40 no[i].pos = i; 41 } 42 sort(no + 1,no + n + 1,cmp); 43 for(int i = 1; i <= n; ++i) ref[no[i].pos] = i; 44 ll ans = 0; 45 for(int i = 1; i <= n; ++i){ 46 Update(ref[i],1); 47 ans += i - Getsum(ref[i]); 48 } 49 printf("%lld\n",ans); 50 } 51 return 0; 52 }
归并排序版:
1 #include <stdio.h> 2 int left[250003],right[250003]; 3 long long count; 4 void merge(int *a,int p,int q,int r) 5 { 6 int i,j,k,n1,n2; 7 n1=q-p+1; 8 n2=r-q; 9 for(i=0;i<n1;i++) 10 { 11 left[i]=a[p+i]; 12 } 13 for(i=0;i<n2;i++) 14 { 15 right[i]=a[q+i+1]; 16 } 17 left[n1]=right[n2]=0x7fffffff; 18 i=j=0; 19 for(k=p;k<=r;k++) 20 { 21 if(left[i]<=right[j]) 22 { 23 a[k]=left[i]; 24 i++; 25 } 26 else 27 { 28 a[k]=right[j]; 29 j++; 30 count+=n1-i;//这里计算的是有多少个后来加入的left【i】会比这个right【j】大 31 } 32 } 33 return; 34 } 35 void mergesort(int *a,int p,int r) 36 { 37 int q; 38 if(p<r) 39 { 40 q=(p+r)>>1; 41 mergesort(a,p,q); 42 mergesort(a,q+1,r); 43 merge(a,p,q,r); 44 } 45 return; 46 } 47 int main() 48 { 49 int n,i,a[500001]; 50 while(~scanf("%d",&n)&&n) 51 { 52 count=0; 53 for(i=0;i<n;i++) 54 { 55 scanf("%d",&a[i]); 56 } 57 mergesort(a,0,n-1); 58 printf("%lld\n",count); 59 } 60 return 0; 61 }