poj 2229 Ultra-QuickSort(树状数组求逆序数)
题目链接:http://poj.org/problem?id=2299
题目大意:给定n个数,要求这些数构成的逆序对的个数。
可以采用归并排序,也可以使用树状数组
可以把数一个个插入到树状数组中, 每插入一个数, 统计比他小的数的个数,对应的逆序为 i- getsum( data[i] ),其中 i 为当前已经插入的数的个数, getsum( data[i] )为比 data[i] 小的数的个数,i- getsum( data[i] ) 即比 data[i] 大的个数, 即逆序的个数。最后需要把所有逆序数求和,就是在插入的过程中边插入边求和。
然而如果数据比较大该怎么办呢?我们就有必要进行一下离散化了
比如 10 30 20 40 50
和 1 3 2 4 5
在求逆序数时他们的意义是一样的。我们可以先快排一次,然后利用hash进行数据离散化处理。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 using namespace std; 7 const int MAX=500010; 8 int N; 9 struct Node{int data,pos;}d[MAX]; 10 int p[MAX]; 11 bool cmp(Node a,Node b) 12 { 13 return a.data<b.data; 14 } 15 class BIT 16 { 17 private: 18 int bit[MAX];//存的是个数,下标是那个数 19 int lowbit(int i) 20 { 21 return i&-i; 22 } 23 public: 24 BIT() 25 { 26 memset(bit,0,sizeof(bit)); 27 } 28 void update(int i,int v) 29 { 30 while(i<=MAX) 31 { 32 bit[i]+=v; 33 i+=lowbit(i); 34 } 35 } 36 int getsum(int i) 37 { 38 int s=0; 39 while(i>0) 40 { 41 s+=bit[i]; 42 i-=lowbit(i); 43 } 44 return s; 45 } 46 }; 47 int main() 48 { 49 while(cin>>N&&N) 50 { 51 for(int i=1;i<=N;i++) 52 { 53 scanf("%d",&d[i].data); 54 d[i].pos=i; 55 } 56 sort(d+1,d+N+1,cmp); 57 memset(p,0,sizeof(p)); 58 for(int i=1;i<=N;i++)//坐标离散化 59 { 60 p[d[i].pos]=i; 61 } 62 __int64 ans=0; 63 BIT tree; 64 for(int i=1;i<=N;i++) 65 { 66 tree.update(p[i],1); 67 ans+=(__int64)(i-tree.getsum(p[i]));//求逆序数 68 } 69 printf("%I64d\n",ans); 70 } 71 return 0; 72 }