NOIp 2013 提高組 火柴排隊 題解

2021-07-24 04:17:39 字數 3055 閱讀 4258

【問題描述】

涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有乙個高度。現在將每盒中的火柴各自 排成一列,同一列火柴的高度互不相同,兩列火柴之間的距離定義為:∑i

=1n(

ai−b

i)2

其中 ai 表示第一列火柴中第 i 個火柴的高度,bi 表示第二列火柴中第 i 個火柴的高度。 每列火柴中相鄰兩根火柴的位置都可以交換,請你通過交換使得兩列火柴之間的距離最小。請問得到這個最小的距離,最少需要交換多少次?如果這個數字太大,請輸出這個最小交換次數對 99,999,997 取模的結果。

【輸入】

輸入檔案為 match.in。 共三行,第一行包含乙個整數 n,表示每盒中火柴的數目。 第二行有 n 個整數,每兩個整數之間用乙個空格隔開,表示第一列火柴的高度。 第三行有 n 個整數,每兩個整數之間用乙個空格隔開,表示第二列火柴的高度。

【輸出】

輸出檔案為 match.out。 輸出共一行,包含乙個整數,表示最少交換次數對 99,999,997 取模的結果。

【輸入輸出樣例 1】

match.in

match.out42

2 3 1 4

3 2 1 4

【輸入輸出樣例說明】

最小距離是 0,最少需要交換 1 次,比如:交換第 1 列的前 2 根火柴或者交換第 2 列的前 2 根火柴。

【輸入輸出樣例 2】

match.in

match.out42

1 3 4 2

1 7 2 4

【輸入輸出樣例說明】

最小距離是 10,最少需要交換 2 次,比如:交換第 1 列的中間 2 根火柴的位置,再交換第 2 列中後 2 根火柴的位置。

【資料範圍】

對於 10%的資料, 1 ≤ n ≤ 10;

對於 30%的資料,1 ≤ n ≤ 100;

對於 100%的資料,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ 2^32 − 1。

【解題思路】

首先如果要解決這道題,就需要先了解一下什麼叫排序不等式。排序不等式完整說明如下:

設數列a=,b=且滿足a1≤a2≤a3≤…≤an,b1≤b2≤b3≤…≤bm。如果c=且c為b中元素的任意乙個排列那麼有如下概念:

將a1b1+a2b2+a3b3+…+anbm稱為順序積之和,簡稱順序和;

將a1bm+a2b m-1 +a3b m-2+…+anb1稱為逆序積之和,簡稱逆序和;

將a1c1+a2c2+a3c3+…+ancn稱為亂序積之和,簡稱亂序和。

那麼有順序和>亂序和>逆序和。①

了解了什麼叫排序不等式,那麼這題看起來就簡單多了。首先把距離公式變一下形,得到:(a

1−b1

)2+(

a2−b

2)2+

(a3−

b3)2

+...

+(an

−bn)

2 去括號得到:(a

12+a

22+a

32+.

..+a

n2+b

12+b

22+b

32+.

..+b

n2)−

2(a1

b1+a

2b2−

...+

anbn

) 由於所有火柴的高度是給定的,所以a1

2+a2

2+a3

2+..

.+an

2+b1

2+b2

2+b3

2+..

.+bn

2 是確定的。

那麼我們只需要a1

b1+a

2b2+

...+

anbn

最大即可。

由以上給出的排序不等式可知,當a1<a2<a3<…<an,b1<b2<b3<…<bn時,整體距離最小。

所以我們可以先將火柴高度陣列a和b進行排序,再將a中最高與b中最高的火柴序號,a中次高與b中次高的火柴序號,…,a中最矮與b中最矮的火柴序號分別進行對映。

對於樣例1,我們建立的對映就如這樣所示:

1 2 3 4

2 1 3 4

對於樣例2,建立的對映就是這樣:

1 2 3 4

1 4 2 3

而進行一次交換就可以消除掉一對逆序對,那麼問題的解即是求對映後下面那個陣列的逆序對個數。至此,問題解決完畢。

可以寫出如下程式:

#include 

#include

#include

#define maxn 101101

#define mod 99999997

using

namespace

std;

long

long i,n,ans=0;

struct matcha[maxn],b[maxn];

int num[maxn]=,t[maxn]=;

int comp(match s,match k)

else t[k++]=num[i++];

while(i<=mid)t[k++]=num[i++];

while(j<=r)t[k++]=num[j++];

for(i=l;i<=r;i++)num[i]=t[i];

}int main()

for(i=1;i<=n;i++)

sort(a+1,a+1+n,comp);

sort(b+1,b+1+n,comp);

for(i=1;i<=n;i++)num[a[i].id]=b[i].id;

merge(1,n);

printf("%lld",ans);

return

0;}

①:嚴格來說,這個不等式是順序和≥亂序和≥逆序和,且當a1=a2=a3=…=an或b1=b2=b3=…=bn時順序和=逆序和。並且當c數列中元素排列順序和b數列中一樣時亂序和=順序和。但是此題中每列中火柴高度都不相同,所以等號無法成立。

NOIP2013提高組 火柴排隊

題目大意 給你兩個有序陣列a,b並定義a,b間的距離為 ai bi 2,要求交換a或者b中的某些元素的位置使得a,b間距離最小。由於 ai bi 2 ai 2 bi 2 2 aibi 而由於題目給定了ai,bi的值,所以 ai 2 bi 2 是定值,要求原式最小就需要 aibi最大。而根據排序不等式...

NOIP2013提高組 火柴排隊

noip2013 提高組 day1 試題 涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有乙個高度。現在將每盒中的火柴各自排成一列,同一列火柴的高度互不相同,兩列火柴之間的距離定義為 其中 ai 表示第一列火柴中第 i個火柴的高度,bi 表示第二列火柴中第 i 個火柴的高度。每列火柴中相鄰兩根火柴...

NOIP2013提高組 火柴排隊

ai bi 2 ai2 bi2 2 ai bi,要使 ai bi 2最小,則需2 ai bi最大。由排序不等式可知兩列數字裡第一大與第一大對應,第二大與第二大對應,第k大與第k大對應,第n大與第n大對應時,ai bi最大。故先將第一列每個數字對映到第二列排名相同的數字,再求需要交換的次數,也就是逆序...