涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有乙個高度。 現在將每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 兩列火柴之間的距離定義為: ∑(ai-bi)^2
其中 ai 表示第一列火柴中第 i 個火柴的高度,bi 表示第二列火柴中第 i 個火柴的高度。
每列火柴中相鄰兩根火柴的位置都可以交換,請你通過交換使得兩列火柴之間的距離最小。請問得到這個最小的距離,最少需要交換多少次?如果這個數字太大,請輸出這個最小交換次數對 99,999,997 取模的結果。
輸入格式:
輸入檔案為 match.in。
共三行,第一行包含乙個整數 n,表示每盒中火柴的數目。
第二行有 n 個整數,每兩個整數之間用乙個空格隔開,表示第一列火柴的高度。
第三行有 n 個整數,每兩個整數之間用乙個空格隔開,表示第二列火柴的高度。
輸出格式:
輸出檔案為 match.out。
輸出共一行,包含乙個整數,表示最少交換次數對 99,999,997 取模的結果。
輸入樣例#1:
【輸入輸出樣例 1】42 3 1 4
3 2 1 4
【輸入輸出樣例 2】
41 3 4 2
1 7 2 4
輸出樣例#1:
【輸入輸出樣例 1】1【輸入輸出樣例 2】
2
【輸入輸出樣例說明1】
最小距離是 0,最少需要交換 1 次,比如:交換第 1 列的前 2 根火柴或者交換第 2 列的前 2 根火柴。
【輸入輸出樣例說明2】
最小距離是 10,最少需要交換 2 次,比如:交換第 1 列的中間 2 根火柴的位置,再交換第 2 列中後 2 根火柴的位置。
【資料範圍】
對於 10%的資料, 1 ≤ n ≤ 10;
對於 30%的資料,1 ≤ n ≤ 100;
對於 60%的資料,1 ≤ n ≤ 1,000;
對於 100%的資料,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint
思路:為了求最小的sigma,我們需要將每列的火柴高度有序化,此時問題就可以看成:要將火柴列a,b都轉化成有序數列需要的交換次數。
那麼,求有序轉化的交換次數的問題,也可以看成求序列逆序對過程,而此題的難點就是需要我們求雙序列逆序對。
首先解決單序列的逆序對問題,這裡我考慮用我最熟悉的資料結構:樹狀陣列(當然線段樹也同樣是解題利器,只不過改點求區間樹狀陣列更簡潔,優雅)。
演算法過程1:利用逆序對定義「1」,陣列a中,若ia[j],則構成一對逆序對,我們可以這樣設計:
確定樹狀陣列代表的是乙個數域,即陣列a中元素值構成的乙個區間,而維護區間中數存在的個數(想象桶排序是怎麼做的?)。
從1到n遍歷陣列a,用a[i]的值更新數域。
因為當前樹狀陣列中1~a[i]維護就是陣列中下標小於i、且小於a[i]的數的個數,令這個數為t,所以已經納入樹狀陣列的數的個數i(已經更新了i個數,對吧?)-t=已經更新過卻大於a[i]的數的個數s,利用「1」,得出s=當前數構成逆序對的個數。
輸出s,演算法完成。
其次,我們再解決雙序列逆序對問題。
演算法過程2:有什麼想法呢?無非和陣列下標和鍵值有關,看看題幹「0 ≤火柴高度≤ maxlongint」,這就說明我們不可拿火柴高度作為樹狀陣列下標,所以實現存下每根火柴在原陣列中的下標a'和b',以火柴高度為關鍵字對陣列a和b排一下序,根據a'為下標,把b'作為鍵值,放入陣列c中,構成乙個次序序列,再用c作為樹狀陣列下標進行演算法1操作。
問題解答完畢。
#include#include#include#define modnum 99999997
using namespace std;
int c[100001],d[100001],n,ans;
struct box
int main()
printf("%d\n",ans%modnum);
return 0;
}
NOIP2013 火柴排隊
題目 分析 a中第幾大一定對應b中第幾大。ab同時移動相當於a移動,相對位置不變。所以,用c i 表示a i 需要移動到的 位置,求其中的逆序對。因為乙個每移動相鄰兩個元素相當於消除乙個逆序對。include include using namespace std const int tmax 10...
NOIP 2013 火柴排隊
題目描述 description 涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有乙個高度。現在將每盒中的火柴各自排成一列,同一列火柴的高度互不相同,兩列火柴之間的距離定義為 其中 ai表示第一列火柴中第 i 個火柴的高度,bi表示第二列火柴中第 i 個火柴的高度。每列火柴中相鄰兩根火柴的位置都可...
NOIp2013 火柴排隊
描述 涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有乙個高度。現在將每盒中的火柴各自排成一列,同一列火柴的高度互不相同,兩列火柴之間的距離定義為 每列火柴中相鄰兩根火柴的位置都可以交換,請你通過交換使得兩列火柴之間的距離最 小。請問得到這個最小的距離,最少需要交換多少次?如果這個數字太大,請輸出...