poj 2299 求逆序数
在只允许相邻两个元素交换的条件下,得到有序序列的交换次数=一个乱序序列的 逆序数
求其逆序数:从左到右找到每一个ai的
一个数组x[] x[j]=1表示此时有j这个数 x[j]=0表示此时还没有j这个数 一开始x全部赋值为0
对于每一个a[i] 求出 x[k]=1 (k<a[i])的个数 再把a[i]赋值为1 再计算 a[i+1]
这里用的树状数组实现的这个过程 辅助数组c[i]表示的是 i点覆盖的这个面积里 x[]=1的个数(回忆一下树状数组这个图)
这里a[i]的值会有999,999,999,这么大 所以还要离散化处理
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #define INF (1<<30) 5 using namespace std; 6 7 int index[500005],n,num[500005]; // 注意n写在外面() 8 __int64 a[500005],c[500005]; 9 10 int cmp(int i,int j) 11 { 12 return a[i]<a[j]; 13 } 14 15 int lowbit(int x) 16 { 17 return x&(-x); 18 } 19 20 __int64 sum(int p) 21 { 22 __int64 ans=0; 23 while(p>0) 24 { 25 ans+=c[p]; 26 p-=lowbit(p); 27 } 28 return ans; 29 } 30 31 void update(int p,int x) 32 { 33 while(p<=n) 34 { 35 c[p]+=x; 36 p+=lowbit(p); 37 } 38 39 } 40 41 int main() 42 { 43 int i,j; 44 while(scanf("%d",&n),n) 45 { 46 for(i=1;i<=n;i++) 47 { 48 scanf("%I64d",&a[i]); 49 index[i]=i; 50 } 51 memset(c,0,sizeof(c)); 52 sort(index+1,index+n+1,cmp); 53 for(i=1;i<=n;i++) 54 num[index[i]]=i; //离散化 55 __int64 ans=0; 56 for(i=1;i<=n;i++) 57 { 58 int yy=i-1-sum(num[i]); // sum 求得的是比a[i]小的数的个数 1代表的是它本身 59 update(num[i],1); //把a[i]添加进去 更新 60 ans+=yy; 61 } 62 printf("%I64d\n",ans); 63 } 64 return 0; 65 }