線段樹動態開點 洛谷P1908逆序對

2021-09-27 18:44:09 字數 1709 閱讀 3432

題目鏈結

題目描述

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

第一行,乙個數n,表示序列中有n個數。

第二行n個數,表示給定的序列。序列中每個數字不超過10^9109

輸出格式

給定序列中逆序對的數目。

輸入輸出樣例輸入6

5 4 2 6 3 1

輸出11

說明/提示

對於25%的資料,n≤2500

對於50%的資料,n≤4×10^4。

對於所有資料,n≤5×10^5

請使用較快的輸入輸出

應該不會n方過50萬吧 by chen_zhe

離散化線段樹的話,寫起來比較複雜,特別是區間離散化的時候就有點麻煩,需要隔板之類的,**量比較大,但動態開點線段樹的話寫起來就非常簡潔了,不容易出錯。

我們一般的線段樹的左右兒子是rt2和rt2+1,但動態開點的話就是由動態分配編號而來的,所以我們需要記錄它的左兒子後右兒子的編號,接下來的操作就是和普通的線段樹差不多了,**中會有注釋。

ac**:

#include

using

namespace std;

#define ll long long

#define lson l,mid,tree[rt].l

#define rson mid+1,r,tree[rt].r

#define ls tree[rt].l

#define rs tree[rt].r

const

int mac=

5e5+10;

const

int inf=

1e9+5;

struct node

tree[mac*32]

;int sz=1;

//動態分配的點的最大編號

ll query

(int l,

int r,

int rt,

int l,

int r)

int mid=

(l+r)

>>1;

if(mid>=l) ans+

=query

(lson,l,r);if

(mid=query

(rson,l,r)

;return ans;

}void

update

(int l,

int r,

int&rt,

int pos)

int mid=

(l+r)

>>1;

if(mid>=pos)

update

(lson,pos)

;//注意這裡傳進去的rt是左兒子的編號

else

update

(rson,pos)

; tree[rt]

.sum=tree[ls]

.sum+tree[rs]

.sum;

}int

main()

printf (

"%lld\n"

,ans)

;return0;

}

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

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

洛谷 P1908 逆序對

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

洛谷P1908 逆序對

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