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
",ans);
63     }
64     return 0;
65 }
原文地址:https://www.cnblogs.com/assult/p/3509042.html