1. 程式人生 > >1394.Minimum Inversion Number(HDU)

1394.Minimum Inversion Number(HDU)

題意理解

給定一個長度N的全排列,對這樣的一個序列對應一個逆序數;現在每次將第一個數放到序列最後一位,形成一個新的序列,這個新序列也對應一個逆序數。求所有這些放法對應逆序數的最小值。逆序數定義:對於i<j,a[i]>a[j]。

問題分析

用樹狀陣列資料結構

轉一:問題分兩層解決,一是求單個序列的逆序數,而是求n個序列逆序數的最小值

轉二:求單個序列的逆序數。就是把序列每個數的逆序數加起來,對於單個數的逆序數,理解為這個數前面從第一位開始到它自己,有幾個數比它大,有幾個算幾個逆序數。再進一步理解,計算它前面有幾個數比它大,可以轉化為前面數的總數量減去前面比它小的數的個數。總數量就是這個數所在的序號減1,前面比它小的數的個數計算方法是每遍歷序列中一個數,就做一個標記為1,表示數已經存在,數一下這些標記的數量就是比它小的數的個數。這是一個字首和。複雜度O(nlogn)

轉三:求n個序列逆序數的最小值。常見思路是一次遍歷序列,總複雜度O(n^2logn)。前後兩個序列變化點在於,第一個數放到最後一位。從這個角度出發,影響分為三方面,這個數本身的逆序數,這個數前面的逆序數和,這個數後面的逆序數和。第一個數所在位置後面的數沒有影響,因為這個數都小於後面的數,不構成逆序對;而第一個數所在位置的前面的每個數都會少一個逆序數,因為比它小的數都少了一個比它大的數;這個數本身的逆序數變大了,從0到n-1-a[i],所有比它的數都構成了逆序對。演算法複雜度為O(nlogn+n)=O(nlogn).

參考:https://blog.csdn.net/ssimple_y/article/details/53744096

其他

這題思路巧,沒思路,問了同學才理解,自己很難想到。

直接求不行,轉化為差值

直接求不行,用變化值分析逐步來求解

靈活用陣列下標,一次遍歷記錄已經處理的資訊,善於利用這些資訊求目標解。

程式碼連結

https://github.com/xierensong/learngit/blob/master/hdu/h1394.cpp