P1908 逆序對 線段樹題解

2021-10-13 15:25:13 字數 1974 閱讀 5958

讀完題目,你的第一想法肯定是直接暴力就能過了。實際上在看完資料之後。。。qaq。好吧,肯定不能暴力,那

麼現在就要去尋找它的特徵。根據它的特徵,我們可以分析出要用線段樹去做這道題。那麼當我們確定這個演算法時,我

來的順序再排回來,然後根據每乙個數的大小對號入座,在入座的過程中我們計算在這個葉子節點的右邊有多少個已經

入座的元素,這時候就體現出來了線段樹的便捷:查詢效率為o(log n) 級別。然後使用sum分別記錄,最後輸出sum。

/*

id: erictian2018

task:

lang: c++

*/#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define inf 0x7ffffff

#define ll long long

//#include

//#include

using

namespace std;

/*輸入:

65 4 2 5 3 1

輸出:*/

ll scan()

for(

; ch>=

'0'&&ch<=

'9'; ch=

getchar()

) x=x*

10+ch-

'0';if(

!flag)

return x;

return

-x;}

ll n;

struct nodetree[

2000010];

ll sum;

/求有多少個逆序對

struct sta[

500100];

// bool

cmp1

(st a,st b)

// bool

cmp2

(st a,st b)

// void

build

(ll l,ll r,ll k)

// ll ask

(ll l,ll r,ll k)

// void

change

(ll l,ll r,ll k)

ll mid=

(tree[k]

.l+tree[k]

.r)/2;

if(l<=mid)

change

(l,r,k*2)

;if(r>mid)

change

(l,r,k*2+

1); tree[k]

.cnt=tree[k*2]

.cnt+tree[k*2+

1].cnt;

}int

main()

//從小到大排序 如果有相同的數則下標較小的排在前面

sort

(a+1

,a+n+

1,cmp1)

;for

(ll i=

1;i<=n;i++

) a[i]

.rank=i;

//根據order的下標再排回來

sort

(a+1

,a+n+

1,cmp2)

;build(1

,n,1);

for(ll i=

1;i<=n;i++

)change

(a[i]

.rank,a[i]

.rank,1)

;cout << sum << endl;

return0;

}

洛谷P1908 逆序對(線段樹解法)

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

P1908 逆序對 題解

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

洛谷 P1908 逆序對(線段樹區間求和 離散化)

逆序對就是序列中 ai aj且i用乙個flag陣列標記哪些數字已經放入陣列中,用線段樹求flag的字首和,求放入的數字前已經放入了多少個比他小的數字。include using namespace std define int long long define ios ios sync with s...