poj2299 树状数组入门题

题意:利用树状数组求逆序数;

思路:因为输入范围较大,先离散化一下,得到的数组a记录了原来数组的大小关系;然后按下标顺序执行add(a[i],1),这样sum(a[i])得到的就是小于等于a[i]的个数,i-sum(a[i])即为a[i]前面比a[i]大的数的个数 //外循环n次并累加i-sum(a[i])得到逆序数

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 struct node{
 9    int v,order;
10 }a[500050];
11 
12 bool cmp(node a, node b){
13    return a.v < b.v;
14 }
15 
16 int aa[500050],c[500050];
17 int n;
18 
19 int lowbit(int x)
20 {
21     return x & (-x);
22 }
23 
24 int sum(int x){
25     int ret = 0;
26     while(x > 0)
27     {
28         ret += c[x]; x -= lowbit(x);
29     }
30     return ret;
31 }
32 
33 void add(int x, int d){
34     while(x <= n){
35         c[x] += d; x += lowbit(x);
36     }
37 }
38 
39 int main()
40 {
41     while(scanf("%d",&n) == 1 && n)
42     {
43         for(int i = 1; i <= n; ++i)
44         {
45             scanf("%d",&a[i].v);
46             a[i].order = i;
47         }
48         sort(a+1,a+n+1,cmp);
49         for(int i = 1; i <= n; ++i)
50         {
51             aa[a[i].order] = i;
52         }
53         memset(c,0,sizeof(c));
54         LL ans = 0;
55         for(int i = 1; i <= n; ++i)
56         {
57             add(aa[i],1);
58             ans += i-sum(aa[i]);
59         }
60         printf("%lld
",ans);
61     }
62     return 0;
63 }
原文地址:https://www.cnblogs.com/Pos-Proteus/p/5555808.html