求排列的逆序數

2021-08-04 03:33:13 字數 1478 閱讀 6451

考慮1,2,…,n (n <= 100000)的排列i1,i2,…,in,如果其中存在j,k,滿足 j < k 且 ij > ik, 那麼就稱(ij,ik)是這個排列的乙個逆序。

乙個排列含有逆序的個數稱為這個排列的逆序數。例如排列 263451 含有8個逆序(2,1),(6,3),(6,4),(6,5),(6,1),(3,1),(4,1),(5,1),因此該排列的逆序數就是8。

現給定1,2,…,n的乙個排列,求它的逆序數。

分治o(nlogn):

1) 將陣列分成兩半,分別求出左半邊的逆序數和右半邊的逆序數

2) 再算有多少逆序是由左半邊取乙個數和右半邊取乙個數構成(要求o(n)實現)

2) 的關鍵:左半邊和右半邊都是排好序的。比如,都是從大到小排序的。這樣,左右半邊只需要從頭到尾各掃一遍,就可以找出由兩邊各取乙個數構成的逆序個數

**如下:

#include using namespace std;

const int maxn = 1000005;

long long a[maxn];

long long t[maxn];

void merge_sort_and_count(long long a, int s, int e, long long t);

void merge(long long a, int s, int m, int e, long long t);

long long count = 0;

int main()

merge_sort_and_count(a, 0, n - 1, t);

cout << count << endl;

} return 0;

} void merge_sort_and_count(long long a, int s, int e, long long t)

int m = s + (e - s) / 2;

merge_sort_and_count(a, s, m, t);

merge_sort_and_count(a, m + 1, e, t);

merge(a, s, m, e, t);

}void merge(long long a, int s, int m, int e, long long t) else

} while(pa <= m)

while(pb <= e)

for(int i = 0; i < pt; i++)

}

事實上稍懂歸併排序的人都知道,其實就在merge函式裡面加了一行

count += pb - (s + pt);
這一行是用來計算 

2) 再算有多少逆序是由左半邊取乙個數和右半邊取乙個數構成(要求o(n)實現)

這個數字原本應該在的位置是(s+pt),實際在的位置是pb,而本來在它右邊的數字依然會在它右邊,應該在它右邊卻在它左邊的數字就與這個數字構成了一對逆序數。

求排列的逆序數

openjudge011 題目 乙個排列含有逆序的個數稱為這個排列的逆序數。例如排列 263451 含有8個逆序 2,1 6,3 6,4 6,5 6,1 3,1 4,1 5,1 因此該排列的逆序數就是8。顯然,由1,2,n 構成的所有n 個排列中,最小的逆序數是0,對應的排列就是1,2,n 最大的逆...

求排列的逆序數

求排列的逆序數 標題 1020 求排列的逆序數 檢視提交統計提問 總時間限制 1000ms 記憶體限制 65536kb 描述在internet上的搜尋引擎經常需要對資訊進行比較,比如可以通過某個人對一些事物的排名來估計他 或她 對各種不同資訊的興趣,從而實現個性化的服務。對於不同的排名結果可以用逆序...

7622 求排列的逆序數

7622 求排列的逆序數 總時間限制 1000ms 記憶體限制 65536kb 描述 在internet上的搜尋引擎經常需要對資訊進行比較,比如可以通過某個人對一些事物的排名來估計他 或她 對各種不同資訊的興趣,從而實現個性化的服務。對於不同的排名結果可以用逆序來評價它們之間的差異。考慮1,2,n的...