樹狀陣列 P1966 火柴排隊 逆序對

2022-07-30 13:48:16 字數 2037 閱讀 6973

1.求兩列之間的距離最小值:其實就是要求a 序列第 k 大的元素必須和序列 b 中第k大的元素的位置必須一樣(通俗的講就是aj與bj大的對應大的,小的對應小的,這樣相減的平方和才最小)

2.火柴高度範圍是2的31次方,如果直接進行運算陣列會超,所以這裡需要離散化,用id來表示數字大小。

3.現在得到兩個id陣列,答案就是a序列不動,b序列變為a序列需要與相鄰元素交換幾次。

4.計算步驟3的方法就是使用乙個陣列q,令 q[a[i]] = b[i] ,相當於以 a[i] 為關鍵字對序列 b[i] 排序。

5.排序移動的次數其實就是序列q中的逆序對的和。

以題目中的輸入一為例:

a:  2 3 1 4

a下標:1 2 3 4

b:  3 2 1 4

b下標:1 2 3 4

再以數字的值排序後:

a:  1 2 3 4

a下標:3 1 2 4

b:  1 2 3 4

b下標:3 2 1 4

令 q[a[i]] = b[i] (這裡a為a下標,b為b下標)

a下標:3 1 2 4

b下標:3 2 1 4

q[3]=3  q[1]=2  q[2]=1  q[4]=4;

對應**中的:

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

q[a[i].id] = b[i].id;

對q陣列的下標整理為從小到大:(這裡的思路理解其實是下標:即a陣列,排序為從小到大,而對應的值:b陣列也跟著排了,兩個陣列一起變化,步驟是不變的,也就是對答案不影響,但是a陣列變得有序了,現在只要讓b陣列有序,計算從此刻開始到有序的步驟既是答案 ,這樣做比雙方未排序前,直接計算b變為a需要的步驟更簡單可實現)q[1]=2  q[2]=1  q[3]=3  q[4]=4;

值序列為2 1 3 4

則2 1 3 4的逆序列和即為答案:1

對應**中的:(這就是逆序對的知識了,不再贅述)

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

#include#include

#include

using

namespace

std;

struct

node

a[100005],b[100005

];long

long c[100005],c2[100005

];int q[100005

];int

n;bool cmp(struct node &a, struct node&b)

int lowbit(int

x)void update(int i, intk)}

long

long getsum(int

i)

return

res;

}int

main()

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

sort(a + 1, a + n + 1

, cmp);

sort(b + 1, b + n + 1

, cmp);

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

q[a[i].id] =b[i].id;

long

long answer = 0

;

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

printf(

"%lld\n

", answer%(99999997

));}

參考:

P1966 火柴排隊 逆序對(歸併,樹狀陣列)

很好的逆序對板子題 求的是 x1 x2 x1 x2 的最小值 x1 x1 x2 x2 2 x1 x2 讓x1 x2最大即可 可以證明將b,c陣列排序後,一一對應的狀態是最大的 ac bdac ada c d a b 逆序對合併時一定要加等號!要判斷q1是否超出mid 爆零體驗 歸併寫法 includ...

洛谷 P1966 火柴排隊(樹狀陣列求逆序)

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

P1966 火柴排隊

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