poj 2299 Ultra-QuickSort(树状数组)
题意:求一个数列的冒泡排序的交换次数;
参考:http://blog.csdn.net/suwei19870312/article/details/5293694
思路:
一个数列的冒泡排序交换次数即为每个数对应的逆序对数之和,朴素的思想是两个for,O(N^2)复杂度;
数字范围是0-999999999,数组大小为500000,所以先离散化,用结构体记录原数列的下标和值;
对于第i个数,利用树状数组的结构,将数列中的数逐个插入到树状数组中并统计当前树状数组中在该数之前的数的个数num,i-num即为该数的逆序对数;
用新数组保存树状数组中数的状态;
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,a[500010]; int num[500010]; long long ans; struct node{ int id,w; }q[500010]; int cmp(node a,node b) { return a.w<b.w; } int lowbit(int i){ return i&(-i); } int sum(int i){ int cnt=0; while(i>=1){ cnt+=num[i];i-=lowbit(i); } return cnt; } void update(int i,int val){ while(i<=n){ num[i]+=val;i+=lowbit(i); } } int main() { int i,j,k; while(scanf("%d",&n)!=EOF){ if(n==0) break; memset(num,0,sizeof(num)); ans=0; for(i=1;i<=n;i++){ q[i].id=i; scanf("%d",&q[i].w); } sort(q+1,q+n+1,cmp); for(i=1;i<=n;i++) a[q[i].id]=i; for(j=1;j<=n;j++) { update(a[j],1); ans+=j-sum(a[j]); } printf("%lld\n",ans); } return 0; }