1. 程式人生 > >逆序數多種求法

逆序數多種求法

初始化 位置 對數 結構體 ref 查詢 -1 思路 sub

在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麽它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。


思路1:暴力查詢,雙重for循環

for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
if(a[i]>a[j])
{
k++;
}

如果數據吧比較多,更新和查找速度變得非常慢。


思路2:排序
比如:2 4 3 1
先查找最小的數1,在它前面有3個數據,全部都比他大,把這個1變成0
再查找除去1最小的2,在它前面有0個數據比他大,然後把這個2變成0


同理,查找3,他前面只有一個數據比他大(2已經變成0)
所以,2 4 3 1這個數列的逆序數為3+0+1=4

如果數據吧比較多,更新和查找會比較繁瑣。


思路3:結構體排序
比如:2 4 3 1
繼續優化思路2:
2 4 3 1(a)
1 1 1 1(b)
現在只需要查找當前數列中最小的數,查找他之前有多少個1,然後把當前位置的1變成0

2 4 3 1
1 1 1 1
1 2 1 4
優化對1查找之後的累加
利用樹狀數組,數組b初始化為1,求b的樹狀數組的前n-1項和,也就是sum(n-1)或者sum(n)-1,然後把n的位置減去1,也就是change(n,-1);

每次查找當前數列最小值,數據多的時候,查找就不那麽方便,所以,我們利用結構體進行排序進行查找過程的優化

利用 a[].val 記錄數據
利用 a[].id 記錄位置
2 4 3 1 (a.val)
1 2 3 4 (a.id)
進行排序之後變成
1 2 3 4 (a.val)
4 1 3 2 (a.id )
1 1 1 1 ( b )

然後我們就可以從a.val的第一個開始查找,依次向後移動,我們利用a.id記錄位置,去判斷和求和;
比如,我們去判斷a.val中的1前面有幾個數,就可以用樹狀數組的知識:sum(a.id)-1或者sum(a.id-1);把1變成0可以用change(a.id,-1);


應用:
51nod 逆序數:
http://www.51nod.com/onlineJudge/submitDetail.html#!judgeId=171479

逆序數多種求法