給定 n 個數組成的陣列,求其逆序對的總數。
逆序對定義為,存在 (i, j) 滿足 i < j 且 a[i] > a[j] 的二元組的數目。
第一行包含乙個整數,表示陣列的項數。
接下來的一行,包含 n 個數(2 <= n <= 100000),依次表示 a[i](a[i] <= 10^9)。
輸出一行表示對應的答案。。
1 3 2 5 4
對於乙個從左往右的序列的,我們可以這樣來統計逆序對數
考慮與前面已經出現的數可能出現逆序
那第乙個數肯定無法構成逆序對
對於第二數 我關注第1個數
對於第三個數 我關注1~2個數
那可以對於每個數 先做個a[i]+1 ~n的查詢 (維護乙個區間和)即這麼多數之前有沒有出現過(但開乙個陣列v記錄)
然後把v[a[i]]++
但發現到數的範圍可能會很大
但是數量是1e5
於是想到離散化
即對於逆序對數 我只關注這些數之間的相對大小關係 辣我排個序搞一下就行
(可以用pair記一下之前的id
也可以只排序再二分定位 )
注意使用long long 逆序對數最大是n2
n
2左右的
//求逆序對數 注意離散化
#include
#include
using
namespace
std;
const
int maxn=1e5+10;
typedef pair pir;
typedef
long
long ll;
int node[maxn];
int a[maxn];
pir b[maxn];//輔助陣列
int n;
inline
int lowbit(int x)
void add(int a,int b)
}ll sum(int n)//字首和
return res;
}int main()
sort(b+1,b+n+1);
int k=1;
a[b[1].second]=k;//離散化後的值
for(int i=2;i<=n;++i)
//for(int i=1;i<=n;++i) cout// for(int i=1;i<=n;++i)
for(int i=1;i<=n;++i)
cout
0;}
//求逆序對數 注意離散化
#include
using
namespace
std;
const
int maxn=1e5+10;
typedef
long
long ll;
int node[maxn];
int a[maxn];
int b[maxn];//輔助陣列
int n;
inline
int lowbit(int x)
void add(int a,int b)
}ll sum(int n)//字首和
return res;
}int main()
sort(b+1,b+n+1);
for(int i=1;i<=n;++i)
//for(int i=1;i<=n;++i) coutfor(int i=1;i<=n;++i)
cout
0;}
尋找逆序對
設a 1.n 是乙個包含n個不同數的陣列。如果在ia j 則 i,j 就成為a中的乙個逆序對 inversion 要確定乙個陣列中的逆序對的個數,可以採取分治法。將a分為兩部分a1和a2,則a中逆序對的數目等於a1中逆序對的數目 a2中逆序對的數目和a1,a2合併時a1中比a2中元素大的數目。inc...
逆序對問題
逆序對問題。給一列數a1 a2,an 求它的逆序對數,即有多少個有序對 i j 使得 i j 但ai aj n 可以高達106 由於 n 的數量級到了106 所以採用o n2 及以上的時間複雜度肯定會超時,所以必須選取o nlog 2n 及以下時間複雜度的演算法。逆序對的求解思路和歸併排序很像,嘗試...
動態逆序對
容易寫掛 對於新手與蒟蒻 洛谷 cdq 如果按照三維偏序那樣求,那麼會漏掉一些情況。所以要跑兩遍cdq。兩遍cdq又會有乙個問題,就是判等於的問題。第一遍cdq第三維判等於,第二遍判不等於.include define ll long long using namespace std inline ...