原題鏈結
貓貓 tom 和小老鼠 jerry 最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。
最近,tom 老貓查閱到乙個人類稱之為「逆序對」的東西,這東西是這樣定義的:對於給定的一段正整數序列,逆序對就是序列中ai>aj
a_i>a_j
ai>aj
且i
i<
j 的有序對。知道這概念後,他們就比賽誰先算出給定的一段正整數序列中逆序對的數目。注意序列中可能有重複數字。
update:資料已加強
第一行,乙個數nnn,表示序列中有n
nn個數。
第二行n
nn個數,表示給定的序列。序列中每個數字不超過109
10^9
109
輸出序列中逆序對的數目。
6
5 4 2 6 3 1
11
對於 25% 的資料,n應該不會o(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請使用較快的輸入輸出
2)
o(n^2)
o(n2
)過 50 萬吧 by chen_zhe
列舉整個陣列,從這個數開始往後列舉,挨個判斷,時間複雜度o(n2)
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 ...