poj 2299 逆序数

来源:互联网 发布:软件外包公司简介 编辑:程序博客网 时间:2024/06/13 01:05

poj 2299 求逆序数

逆序数的定义:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。如2431中,21434131是逆序,逆序数是4,为偶排列。

一,利用归并排序求逆序数

利用归并排序求逆序数的原理:利用归并求逆序是指在对子序列s1s2归并的时候,如果s1[i] > s2[j], 那么子序列s1istrlen(s1) 都大于s2[j],也就是构成了逆序,那么逆序数+= strlen(s1) - i + 1; 

#include <iostream>#include <algorithm>using namespace std;__int64 change;int arr[505000];//升序void merge(int arr[], int leftPos, int rightPos, int rightEnd) //合并{int *temp = (int*)malloc((rightEnd-leftPos+3)*sizeof(int));int leftEnd = rightPos - 1;int tempPos = 0;int start = leftPos;while(leftPos <= leftEnd && rightPos <= rightEnd){if(arr[leftPos] <= arr[rightPos]){temp[tempPos++] = arr[leftPos++];}else{temp[tempPos++] = arr[rightPos++];change += leftEnd - leftPos + 1; //在归并排序中加上这句代码即可}}while(leftPos <= leftEnd){temp[tempPos++] = arr[leftPos++];}while(rightPos <= rightEnd){temp[tempPos++] = arr[rightPos++];}for(int i=0; i<tempPos; i++){arr[start+i] = temp[i];}free(temp);}void mergeSort(int arr[], int left, int right) //归并排序{if(left < right){int center = (left + right) / 2;mergeSort(arr,left,center);mergeSort(arr,center+1,right);merge(arr,left,center+1,right);}}int main(){int n;while(cin>>n,n){change = 0;for(int i=0; i<n; i++){cin>>arr[i];}mergeSort(arr,0,n-1);cout<<change<<endl;}return 0;}

二,离散化+树状数组

//先离散化,再利用树状数组#include "stdafx.h"#include <iostream>#include <algorithm>using namespace std;const int MAXN = 500010;int sum[MAXN];int num[MAXN];struct Point{int val;int id;bool const operator < (const struct Point& a)const{return val < a.val;}}p[MAXN];int lowbit(int x){return x & (-x);}void update(int x, int val){while(x < MAXN){sum[x] += val;x = x + lowbit(x);}}int getSum(int x){int s = 0;while(x > 0){s += sum[x];x = x - lowbit(x);}return s;}int main(){int n;while(cin>>n,n){memset(sum,0,sizeof(sum));for(int i=1; i<=n; i++){cin>>p[i].val;p[i].id = i;}//离散化,即将 100 20 2000 1000等,转化为 2 1 4 3sort(p+1,p+n+1);for(int i=1; i<=n; i++){num[i] = p[i].id;}__int64 ans = 0;for(int i=n; i>=1; i--)  //从后往前操作,具体解释看下一篇树状数组应用{ans += getSum(num[i]);update(num[i],1);}cout<<ans<<endl;}return 0;}


 

原创粉丝点击