洛谷1966 火柴排隊(逆序對)

2022-05-14 14:18:14 字數 1261 閱讀 2405

點此看題面

大致題意:有\(a\)和\(b\)兩個陣列,問你要將\(b\)進行多少次相鄰兩數交換操作,才能使得\(\sum_^n(a_i-b_i)^2\)最小。

不難猜到,當\(a\)中第\(i\)小的數與\(b\)中第\(i\)小的數配對時,值最小。

證明以\(n=2\)為例(\(n>2\)同理),設\(a_1,此時只有兩種匹配方式:

\(s_1=(a_1-b_1)^2+(a_2-b_2)^2=a_1^2+a_2^2+b_1^2+b_2^2-2a_1b_1-2a_2b_2\)

\(s_2=(a_1-b_2)^2+(a_2-b_1)^2=a_1^2+a_2^2+b_1^2+b_2^2-2a_1b_2-2a_2b_1\)

則用\(s_1\)減\(s_2\)得:

\[s_1-s_2=-2(a_1b_1+a_2b_2-a_1b_2-a_2b_1)=-2(a_2-a_1)(b_2-b_1)

\]\[\because a_1

原命題得證。

設\(rb_i\)為\(b_i\)是\(b\)序列中第幾小的數,則我們可以得出乙個序列\(s\),其中\(s_i\)表示\(a\)序列中第\(rb_i\)小的數的位置

那麼題意就變成了求要對\(s\)序列進行多少次氣泡排序操作,才可以使\(s\)有序。

根據乙個著名定理,氣泡排序操作次數即為逆序對個數。

因此我們直接逆序對做即可。

我採用的是歸併排序,具體實現見**。

#include#define tp template#define ts template#define reg register

#define ri reg int

#define con const

#define ci con int&

#define i inline

#define w while

#define n 100000

#define x 99999997

#define inc(x,y) ((x+=(y))>=x&&(x-=x))

using namespace std;

int n,s[n+5];

struct data

i bool operator < (con data& o) con

public:

i void solve()

}m;int main()

洛谷P1966 火柴排隊 逆序對

題目鏈結 不算很難的一道題 首先要保證權值最小,不難想到一種貪心策略,即把兩個序列中rank相同的數放到同乙個位置 證明也比較trivial。假設 a 中有兩個元素 a,b b 中有兩個元素 c,d 然後分別討論一下當 a b 時 c 與 a 對應優還是與 b 對應優。化簡的時候直接對兩個式子做差。...

洛谷 1966 火柴排隊

題目描述 涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有乙個高度。現在將每盒中的火柴各自排成一列,同一列火柴的高度互不相同,兩列火柴之間的距離定義為 a i bi 2 ai bi 2 ai b i 2其中ai 表示第一列火柴中第i個火柴的高度,bi 表示第二列火柴中第 iii 個火柴的高度。每列...

求逆序對 思維 火柴排隊(洛谷 P1966)

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