POJ 2299 線段樹或樹狀陣列或歸併排序

2021-09-11 09:26:08 字數 3142 閱讀 9896

ultra-quicksort

剛剛學線性代數學到的逆序數,用多重迴圈果然超時,剛開始的時候完全沒有線段樹的思路,後來看了別人的思路,發現真的妙啊,開心的飛起來,雖然我後面又因為把小括號寫成中括號的問題wa了一晚上。比如說9 1 0 5 4這個序列,我們記錄一下他們的序號位置,然後再排個序:01

459在原序列中的位置32

541開始我們把每個節點的數值都設定為1;

我們從最小數0開始看,他原來的位置是3,說明它前面比它大的有兩個數,我們查詢從1到(位置-1),也就是1到2,查詢這段區間的總和為2;然後我們把這個位置的和-1,再依次往後看次小數。我們把所有查詢的數字加起來就是總的逆序數了。

#include

#include

#include

#include

using namespace std;

const

int inf=

0x3f3f3f3f

;const

int maxn=

500001

;int addmark[maxn<<2]

,seqtree[maxn<<2]

;struct nodea[maxn]

;int

cmp(node a,node b)

void

maketree

(int node,

int begin,

int end)

int mid=

(begin+end)/2

;maketree

(node<<

1,begin,mid)

;maketree

(node<<1|

1,mid+

1,end)

; seqtree[node]

=seqtree[node<<1]

+seqtree[node<<1|

1];}

void

update

(int node,

int begin,

int end,

int pos,

int grade)

int mid=

(begin+end)/2

;update

(node<<

1,begin,mid,pos,grade)

;update

(node<<1|

1,mid+

1,end,pos,grade)

; seqtree[node]

=seqtree[node<<1]

+seqtree[node<<1|

1];}

intquery

(int node,

int begin,

int end,

int l,

int r)

intmain()

sort

(a+1

,a+n+

1,cmp)

;for

(i=1

;i<=n;i++

) cout<}}

歸併排序需要來回不斷交換區間內的元素,我們只需要記錄k指標和j指標兩者的差值,就是在此段區間內比j指向的這個數大的數的個數,我們把這個值累加就可以。

#include

#include

#include

#include

using namespace std;

int a[

500010

],b[

500010];

long

long sum;

void

mergei

(int a,

int low,

int mid,

int high)

else

}while

(i<=mid)

b[k++

]=a[i++];

while

(j<=high)

b[k++

]=a[j++];

for(i=low;i<=high;i++

) a[i]

=b[i];}

void

merge_sort

(int a,

int low,

int high)

}int

main()

merge_sort

(a,1

,n);

cout<}}

樹狀陣列充分利用二進位制的特點組成,每次查詢i可以查詢出前i項的和,我們的思路是先把輸入的資料離散化一下,然後以離散後的資料進行更新和查詢,我們要查詢出當前數字前面有幾個比他大的數字,我們可以反著求,用前面的數字個數-比當前數字小的個數。而這個小的個數就是用樹狀陣列的查詢,開始時,我們把tree陣列初始化為0,每當查詢完畢乙個數,我們就把tree[這個數]加一,這樣我們只需要看看當前數字前面總共有多少個1就行了。

#include

#include

#include

#include

using namespace std;

int tree[

500001

],n;

struct nodea[

500001];

intlowbit

(int x)

void

update

(int x,

int k)

}int

query

(int x)

return sum;

}int

cmp(node a,node b)

intcmp1

(node a,node b)

intmain()

sort

(a+1

,a+n+

1,cmp)

;for

(i=1

;i<=n;i++

)sort

(a+1

,a+n+

1,cmp1)

;for

(i=1

;i<=n;i++

) cout<}}

poj 2299 樹狀陣列

題目大意 本題要用到樹狀陣列的離散化處理,因為資料太大 1 999999999 但還是wa了兩次,c i 的範圍計算錯誤,要用到long long 從後向前處理,每次處理乙個數,求比這個數小的個數。poj 2299 樹狀陣列 include include include include inclu...

POJ 2299(樹狀陣列,離散化)

題意 求逆序數 題解 可以將數字插入樹狀陣列,每次統計比單前數字小的個數,我們將每個數字的權值設定為1,那麼只要求在他前面數字的和就知道了,對應的逆序數格個數是i sum a i 這裡使用樹狀 陣列維護區間和 這一題由於數字範圍過大,記憶體無法承受如此大的空間,我們可以看到n最多才5e5,所以最多有...

poj 2299 樹狀陣列 離散化

樹狀陣列求逆序數 離散化 求逆序數時,加入當前數字,然後統計大於當前數字的數字個數,題目資料很大,需先將其離散化。include include include define n 500005 define lowbit x x x using namespace std int c n a n s...