# 逆序數對 #### 定義: 設一數列s[10]與其中兩index:i,j,當0<=i<j<=9 且s[i]>s[j]時,兩數被稱為逆序數對 #### 作法: 1. 掃一遍陣列 => 索引號i為嚴格遞增 2. 根據定義,只要找小於i的所有數中大於s[i]的個數就是當前的逆序數對個數 3. 掃完後把所有找到的逆序數對相加就是所有的逆序數對 #### 時間複雜度優化 : 在找前i個有幾個數比s[i]大時,可以利用BIT技巧計算 ##### 比s[i]大的各數=BIT裡的數-BIT的query(比s[i]小的數) ```cpp= int bit[MAXN]; void update(int n){ while(n<=MAXN){ bit[n]++; n+=n&-n; } } int query(int n){ int sum=0; while(n>0){ sum+=bit[n]; n-=n&-n; } return sum; } int main(){ ...... int ans=0; for(int i=0;i<n;i++){ ans+=i-query(s[i]); update(s[i]); } } ``` #### 記憶體優化 : 離散化: 因為我們只要比大小,所以可以利用離散化把索引值壓縮到BIT的大小 ```cpp= sort(descrete.begin(),descrete.end()); for(int i=0;i<n;i++){ arr[i]=lower_bound(descrete.begin(),descrete.end(),arr[i])-descrete.begin()+1; //+1是因為BIT的index要從1開始 } ``` #### 完整程式碼 ```cpp= #include <bits/stdc++.h> #define MAXN 10005 using namespace std; int bit[MAXN]={0}; void update(int n){ //單點修改 while(n<=MAXN){ bit[n]++; n+=n&-n; } } int query(int n){ //前綴和查詢 int sum=0; while(n>0){ sum+=bit[n]; n-=n&-n; } return sum; } int main(){ int n; cin >> n; vector<int> arr(n); //紀錄數列 vector<int> descrete; //利散化用 for(int i=0;i<n;i++){ cin >> arr[i]; descrete.push_back(arr[i]); } //離散化 sort(descrete.begin(),descrete.end()); for(int i=0;i<n;i++){ arr[i]=lower_bound(descrete.begin(),descrete.end(),arr[i])-descrete.begin()+1; } //BIT維護&計算答案 int ans=0; for(int i=0;i<n;i++){ ans+=i-query(arr[i]); update(arr[i]); } cout << ans << '\n'; return 0; } ```