P1908 逆序對 題解

2022-04-29 20:33:12 字數 2213 閱讀 7384

原題鏈結

貓貓 tom 和小老鼠 jerry 最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。

最近,tom 老貓查閱到乙個人類稱之為「逆序對」的東西,這東西是這樣定義的:對於給定的一段正整數序列,逆序對就是序列中a

i>aj

a_i>a_j

ai​>aj

​且i

i<

j 的有序對。知道這概念後,他們就比賽誰先算出給定的一段正整數序列中逆序對的數目。注意序列中可能有重複數字。

update:資料已加強

第一行,乙個數n

nn,表示序列中有n

nn個數。

第二行n

nn個數,表示給定的序列。序列中每個數字不超過109

10^9

109

輸出序列中逆序對的數目。

6

5 4 2 6 3 1

11
對於 25% 的資料,n

≤2500

n \leq 2500

n≤2500

對於 50% 的資料,n≤4

×104

n \leq 4 \times 10^4

n≤4×10

4對於所有資料,n≤5

×105

n \leq 5 \times 10^5

n≤5×10

5請使用較快的輸入輸出

應該不會o(n

2)

o(n^2)

o(n2

)過 50 萬吧 by chen_zhe

列舉整個陣列,從這個數開始往後列舉,挨個判斷,時間複雜度o(n

2)

o(n^2)

o(n2

)

#include

using

namespace std;

int n;

int a[

500010];

int cnt;

intmain()

for(

int i=

1;i<=n;i++)}

}printf

("%d"

,cnt)

;return0;

}

考慮一下,是否可以將序列分段,利用合併排序思想;

先分段步長為1,然後使序列有序,計算每一組序列的逆序對數目,然後步長2、4、直到步長等於整個序列

每一組序列a[i]a[j],如果a[i] < a[j]那麼不是逆序對,直接將a[j]複製到新陣列裡,如果a[i]>a[j]那麼a[i]這一段後面所有資料都大於a[j],sum直接加mid-i+1即可(因為序列之從步長遞增將每一組序列內部已經排好序了),最後注意將新陣列裡面資料複製到a陣列相應的位置中。

#include

using

namespace std;

#define maxn 40001

int a[maxn]

,temp[maxn]

;int sum=

0,n;

intmergepass

(int left,

int mid,

int right)

}///剩餘部分加進去

while

(i<=mid)

temp[k++

]= a[i++];

while

(j<=right)

temp[k++

]= a[j++];

for(

int i=

0;i) a[left+i]

= temp[i]

;///最後將這段改動的資料仍然放在a陣列中

}void

mergesort

(int left,

int right)

}int

main()

洛谷 題解 P1908 逆序對

一開始竟然妄想用 n 2 的演算法過這題,然而這是不可能的 所以只好寫歸併排序來求逆序対惹 比如將下面兩個區間排序 3 4 7 9 1 5 8 10首先將右區間的 1 取出,放到 r k 中,此時 1 是比每個 a i 中的元素都小,也就是說此時 i 的指標指向 a 1 的位置,此刻得到的逆序對的數...

題解 P1908 逆序對 歸併演算法

先吐槽 這題做了兩天,昨天講分治,老師用歸併講了一遍,今天又用樹狀陣列講了一遍 歸併不難,啊啊啊我居然才調出來 歸併兩個陣列時,對於第二個陣列的元素a c2 它與第乙個陣列中目前還沒歸到總數組裡的元素形成逆序對 c1,c2是指標,對於a c2 它與a c1.mid 構成逆序對,貢獻對 臨時陣列c開成...

洛谷 P1908 逆序對

題目描述 貓貓tom和小老鼠jerry最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。最近,tom老貓查閱到乙個人類稱之為 逆序對 的東西,這東西是這樣定義的 對於給定的一段正整數序列,逆序對就是序列中ai aj且i var i,n,t longint ...