P1966 火柴排隊

2022-05-05 20:03:07 字數 1650 閱讀 6991

題目描述

涵涵有兩盒火柴,每盒裝有 nn 根火柴,每根火柴都有乙個高度。 現在將每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 兩列火柴之間的距離定義為: ¥\(\sum (a_i-b_i)^2∑(a

i​ −b

i​ )

2\)其中 a_i

​ 表示第一列火柴中第 i 個火柴的高度, b_i

​ 表示第二列火柴中第 i 個火柴的高度。

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

輸入輸出格式

輸入格式:

共三行,第一行包含乙個整數 nn ,表示每盒中火柴的數目。

第二行有 n n 個整數,每兩個整數之間用乙個空格隔開,表示第一列火柴的高度。

第三行有 nn 個整數,每兩個整數之間用乙個空格隔開,表示第二列火柴的高度。

輸出格式:

乙個整數,表示最少交換次數對 99,999,99799,999,997 取模的結果。

很經典的一道題, 以前就做過了, 今天培訓講到, 寫部落格複習一下

首先我們可以 瞎j8猜 判斷出: 當兩個火柴序列在本序列內排序同另乙個序列相同, 則答案最優。 什麼意思呢?就是當在第乙個序列中, 排名為 \(x\) 的火柴棒排在第 \(p\) 個, 而在第二個序列中排名為 \(x\) 的火柴棒也排在第 \(p\) 個, 當每乙個火柴棒滿足這一條件時, 得出的和最小, 顯然轉化為逆序對的求解問題。

在一般的逆序對問題中, 通常只給出乙個序列, 直接求逆序對的個數。 但是事實上, 這不是等價於給你兩個序列, 乙個無序, 另乙個有序 \(1, 2, 3, 4..., n\) 求解將第乙個排序成為有序的那個的逆序對個數嗎? 換句話說, 本題也是求解逆序對, 只是已經給出排序的依據(可以a為依據排序b, 亦可以以b為依據排序a), 而不是普通的有序序列。

所以我們先對\(a,b\)按照值的大小排序, 以有序序列為橋梁, 找出 \(a,b\) 的對應關係(這個過程中可以離散化一下), 再(按照 \(a\) 的原始順序)排序回來, 就得到了(以 \(a\) 為依據)的 \(b\) 的排序順序了

樹狀陣列求解逆序對即可

#include#include#include#include#include#include#define lowbit(i) ((i) & (-i))

typedef long long ll;

using namespace std;

ll rd()

while(c >= '0' && c <= '9')

return flag * out;

}const ll maxn = 10000019,m = 99999997;

ll num;

ll c[maxn];

void update(ll x,ll val)

ll getsum(ll x)

struct aa[maxn],b[maxn],i[maxn];

bool cmp1(a a,a b)

bool cmp2(a a,a b)

int main()

printf("%lld\n",ans);

return 0;

}

P1966 火柴排隊

題意 求兩個為n的序列貢獻值最小需要怎麼移動才能達到,移動 交換相鄰元素,貢獻值 ai bi 2。顯然可以猜出來,排序過後對應的最小。事實上也可以用反證法證明aac bd最小 我們令上面的序列不動,只動下面的序列,首先得到下面序列應該是怎麼樣的。用標號來標誌原來位置,排序過後,把對應位置賦值到陣列上...

P1966 火柴排隊

讓a,b序列中大小排名相對應即可 若a中第j大的位於i,則應該b中第j大位於i 證明 假如a1則排列方式有 a1,a2,b1,b2或 a1,a2,b2,b1那麼 對於這兩種情況上,平方並做差,即可得以上結論 然而大問題是這樣離散化後怎麼搞出交換幾次呢 離散化後 c b i 然後若我們最後拍完序 定然...

P1966 火柴排隊

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