NOIP2013 逆序對 火柴排隊

2021-08-29 03:57:43 字數 1980 閱讀 2151

題目: 涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有乙個高度。 現在將每盒中的火柴各自排成一列, 同一列火柴的高度互不相同,

兩列火柴之間的距離定義為: ∑(ai-bi)^2

其中 ai 表示第一列火柴中第 i 個火柴的高度,bi 表示第二列火柴中第 i 個火柴的高度。

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

99,999,997 取模的結果。

分析:

我們觀察距離的定義:

所以我們要求sigma(a[i]*b[i])的最大值

顯然讓a中最大的乘以b中最大的可以得到最大值,而我們同時交換兩個序列中的數字等價於乙個序列不動,交換另乙個序列中的數字

那麼我們就可以構造出乙個陣列c,c[i]代表a序列不動,b序列中的第i個數字要移動到位置c[i]上,此時c中的逆序對個數就是我們的最小交換次數

可以用歸併排序或者樹狀陣列求

**(樹狀陣列):

#include

#define ll long long

using

namespace std;

#define mod 99999997

long

long tr[

100010];

const

int n=

100005

;int n;

int bb[n]

;void

add(

int k,ll num)

}int

read

(int k)

return sum;

}struct node

aa[100010];

bool

cmp(node a,node b)

struct premu1

a[n]

;struct premu2

b[n]

;bool

cmpa

(premu1 x,premu1 y)

bool

cmpb

(premu2 x,premu2 y)

bool

cmpc

(premu2 x,premu2 y)

int sum[n]

;int

main()

for(

int i=

1;i<=n;i++

)sort

(a+1

,a+n+

1,cmpa)

;sort

(b+1

,b+n+

1,cmpb)

;for

(int i=

1;i<=n;i++

) b[i]

.tree=a[i]

.num;

sort

(b+1

,b+n+

1,cmpc)

;for

(int i=

1;i<=n;i++

) sum[i]

=b[i]

.tree;

memset

(tr,0,

sizeof

(tr));

for(

int i=

1;i<=n;i++

)sort

(aa+

1,aa+

1+n,cmp)

;int cnt =1;

for(

int i=

1;i<=n;i++

) ll summ =0;

for(

int i=

1;i<=n;i++

)printf

("%lld\n"

,summ)

;return0;

}

NOIP2013 火柴排隊(逆序對)

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

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 個火柴的高度。每列火柴中相鄰兩根火柴的位置都可...