我们都知道,求逆序对数量可以用归并排序解决。但是用归并排序只能解决静态的序列问题,没有扩展的区间。因此就有了用权值线段树求逆序对的方法。

 1 #include<iostream>
 2 #include<iomanip>
 3 #include<ctime>
 4 #include<climits>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<vector>
 8 #include<cstring>
 9 #include<cstdio>
10 #include<cstdlib>
11 using namespace std;
12 typedef unsigned long long LL;
13 #define rep(i,a,b) for(int i=a;i<=b;i++)
14 #define dep(i,a,b) for(int i=a;i>=b;i--)
15 inline int read(){
16     int x=0;char ch=getchar();
17     while(ch<'0'||ch>'9'){
18         ch=getchar();
19     }
20     while(ch>='0'&&ch<='9'){
21         x=x*10+ch-'0';
22         ch=getchar();
23     }
24     return x;
25 }
26 const int M=100001;
27 int sum[M<<2]={0};//建立一棵空线段树
28 int a[M];//如果a[i]数据范围较大,则需要离散化
29 #define lson l,m,rt<<1
30 #define rson m+1,r,rt<<1|1
31 void update(int rt){
32     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
33 }
34 void modify(int l,int r,int rt,int p){
35     if(l==r){
36         sum[rt]++;//权值p累和
37         return;
38     }
39     int m=(l+r)>>1;
40     if(p<=m)modify(lson,p);
41     else modify(rson,p);
42     update(rt);
43 }
44 int query(int l,int r,int rt,int nowl,int nowr){
45     if(nowl<=l&&r<=nowr)return sum[rt];
46     int ans=0;
47     int m=(l+r)>>1;
48     if(nowl<=m)ans+=query(lson,nowl,nowr);
49     if(m<nowr)ans+=query(rson,nowl,nowr);
50     return ans;
51 }
52 int main(){
53     int n=read();
54     rep(i,1,n)a[i]=read();
55     LL ans=0;
56     rep(i,1,n){
57         ans+=query(1,n,1,a[i]+1,M);//求以a[i]为末项的逆序对数时,转化为求a[1..(i-1)]中权值大于a[i]的数的个数
58         modify(1,n,1,a[i]);//权值a[i]累积入权值线段树
59     }
60     cout<<ans<<endl;
61     return 0;
62 }

附上百度的离散化定义:

把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:
原数据:1,999,100000,15;处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
处理后:{3,4},{2,6},{1,5};