树状数组--求逆序对-离散化

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long 
 6 #define MAX 500005
 7 using namespace std;
 8 
 9 struct Node
10 {
11     int val,pos;
12     bool operator<(const Node& A)const
13     {
14         return val<A.val;
15     }
16 }d[MAX];
17 int n,tree[MAX],p[MAX];
18 
19 inline int lowbit(int x)
20 {
21     return x&(-x);
22 }
23 
24 void ADD(int pos,int x)
25 {
26     int i=pos;
27     for(;i<=n;i+=lowbit(i))
28     {
29         tree[i]+=x;
30     }
31 }
32 
33 ll Getsum(int N)
34 {
35     ll ans=0;
36     for(int i=N;i>0;i-=lowbit(i))
37     {
38         ans+=tree[i];
39     }
40     return ans;
41 }
42 
43 int main()
44 {
45     while(~scanf("%d",&n)&&n)
46     {
47         memset(p,0,sizeof(p));
48         memset(tree,0,sizeof(tree));
49         for(int i=1;i<=n;i++)
50         {
51             scanf("%d",&d[i].val);
52             d[i].pos=i;
53         }
54         sort(d+1,d+n+1);
55         //对原数组离散化;存到新的数组p中,是源数组的一一映射;
56         int num=1;
57         p[d[1].pos]=1;
58         for(int i=2;i<=n;i++)
59         {
60             if(d[i].val==d[i-1].val)
61                 p[d[i].pos]=num;
62             else
63                 p[d[i].pos]=++num;
64         }
65         ll ans=0;
66         for(int i=1;i<=n;i++)
67         {
68             ADD(p[i],1);
69             ans+=i-Getsum(p[i]);
70             /*Getsum求的是在插入这个值的时候自己的前面已经插了几个值,
71               按输入顺序插入的,大小是经过离散的;
72               到目前一共插了i个数,插到他前面的是顺序比他靠前,值比他小的,
73               后面的是顺序比他小但是值比他大的,也就和他构成逆序数对的数;*/
74         }
75         printf("%lld\n",ans);
76         
77     }
78 
79     return 0;
80 }

 

posted on 2015-06-02 16:12  bai_yan  阅读(149)  评论(0编辑  收藏  举报

导航