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陣列,排序為從小到大,而對應的值:b陣列也跟著排了,兩個陣列一起變化,步驟是不變的,也就是對答案不影響,但是a陣列變得有序了,現在只要讓b陣列有序,計算從此刻開始到有序的步驟既是答案 ,這樣做比雙方未排序前,直接計算b變為a需要的步驟更簡單可實現)q[1]=2 q[2]=1 q[3]=3 q[4]=4;q[a[i].id] = b[i].id;
值序列為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最小 我們令上面的序列不動,只動下面的序列,首先得到下面序列應該是怎麼樣的。用標號來標誌原來位置,排序過後,把對應位置賦值到陣列上...