NOIP2013D1T2 火柴排隊 題解

2021-07-24 17:07:15 字數 1793 閱讀 5715

(題目描述略)

對於距離最小,其貪心策略為將兩序列公升序排序後比較。以下為簡易的證明:

設對任意 a1 < a2,b1 < b2,

第一種排布是 ..a1a2..,..b1b2..,此時距離為 (a1 - b1) ^ 2 + (a2 - b2) ^ 2 (1),

第二種排布是 ..a1a2..,..b2b1..,此時距離為 (a1 - b2) ^ 2 + (a2 - b1) ^ 2 (2),

用(1)式減去(2)式,得差為 2(a1 - a2)(b2 - b1) < 0,

故(1)<(2),貪心策略得證。

於是,原題轉化為,求最少的相鄰交換次數使得兩序列的大小順序相同。考慮到兩序列的大小順序之間的關係不方便確定,我們可以用離散化的方法對序列預處理,再求其逆序對即可。

將序列預處理的過程如下:首先現將第乙個序列中的值離散到整數區間 [1, n] 中,記為 order1[1..n],其中 order1[i] 表示第乙個序列中下標為 i 的數值是序列中第 order1[i] 小的數值;再將第二個序列離散化,記為 order2[1..n],其中 order2[i] 表示第二個序列中第 i 小的數值的下標。

所以,我們可以發現,第乙個序列中下標為 i 的數值對應第二個序列中下標為 order2[order1[i]] 的數值。於是,原題再次轉化為,求最少的相鄰交換次數使得序列 order2[order1[1..n]] 變成公升序序列。對序列 order2[order1[1..n]] 求逆序對即為結果。

關於逆序對的求法,常見的有樹狀陣列和歸併排序兩種。對於樹狀陣列而言,我們令 i 公升序依次在樹狀陣列下標為 order2[order1[i]] 中插入 i,每加入乙個數統計當前狀態下在其前面的數,即統計 j 的個數使得 i > j 且 order2[order1[i]] > order2[order1[j]],在用 i 減去統計結果即為所有以 i 為起始的逆序對個數。求和即可。

對於歸併排序而言,在每次對序列 order2[order1[i]] 歸併的過程中,設前半段掃瞄指標 i,後半段掃瞄指標 j,後半段起始指標 m,若掃瞄中發現 order2[order1[i]] > order2[order1[j]],則逆序對計數器加上 m - i。因為此時對於任意 i < k < m,均有 order2[order1[k - 1]] < order2[order1[k]],所以對於任意 i ≤ k < m,均有 order2[order1[k]] > order2[order1[j]]。一旦發現,掃瞄指標 j 右移,故不會重複計算。每次歸併計算出當前兩段有序子串行之間的逆序對個數並將兩段有序子串行合併成一段新的有序有序子串行,這樣便能統計出所有原序列中的逆序對。

這兩種演算法的時間效率類似,均為 o(nlogn) 級別的演算法;預處理中的離散化操作因用快排故時間效率也為 o(nlogn)。於是,總算法時間複雜度為 o(nlogn)。

**如下:(樹狀陣列版本)

#include"stdio.h"

#include"stdlib.h"

#include"string.h"

#define lowbit(x) ((x)&-(x))

int high[100005],sum[100005],order1[100005],order2[100005];

int cmp(const

void *p,const

void *q)

int main()

printf("%d",ans);

return

0;}

不得不說,本題離散化的思想有些複雜,但保持思路清晰仍然可解。當然,本題解只給出了樹狀陣列版本的**實現,對於歸併排序版本的**實現請讀者自行**。

NOIP2013 D1 T2火柴排隊

涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有乙個高度。現在將每盒中的火柴各自排成一列,同一列火柴的高度互不相同,兩列火柴之間的距離定義為 ai bi 2 其中 ai 表示第一列火柴中第 i 個火柴的高度,bi 表示第二列火柴中第 i 個火柴的高度。每列火柴中相鄰兩根火柴的位置都可以交換,請你通...

noip2013 d1t2 火柴排隊

看不出是逆序對.感覺藥丸 首先要看出最優解就是兩個陣列均有序的時候 再對兩個陣列的下標求逆序對即可 歸併 樹狀陣列 1 include2 include3 include4 include5 include6 define modd 99999997 7using namespace std 8co...

2013NOIP D1 T2 火柴排隊

題目點這裡 題目大意 有兩列火柴,給出他們的根數和他們對應的長度ai,bi,並且規定距離為 解題思路 怎麼使距離最小?哈哈哈哈,是在兩個佇列裡面的火柴相對應 a集合火柴中第i小對應b集合中第i小 將兩個集合排序 為了讓ab相對應 因為排好序a,b是最小的,所以a下標與b下標就要對應 然後按照a去處理...