樹狀陣列的原理及其應用(HH的項鍊)

2021-10-08 13:56:25 字數 2075 閱讀 3793

樹狀陣列主要用於查詢和計算字首和,時間複雜度為o(nlogn),普通的陣列的時間複雜度o(n^2)在大資料下是不可以接受的,所以樹狀陣列是乙個非常良好的資料結構。

以上是樹狀陣列基本操作。

下面是在洛谷上做到的乙個樹狀陣列這個資料結構的應用:

題目描述

hh 有一串由各種漂亮的貝殼組成的項鍊。hh 相信不同的貝殼會帶來好運,所以每次散步完後,他都會隨意取出一段貝殼,思考它們所表達的含義。hh 不斷地收集新的貝殼,因此,他的項鍊變得越來越長。

有一天,他突然提出了乙個問題:某一段貝殼中,包含了多少種不同的貝殼?這個問題很難回答…… 因為項鍊實在是太長了。於是,他只好求助睿智的你,來解決這個問題。

輸入格式

一行乙個正整數 n,表示項鍊長度。

第二行 n 個正整數 ai,表示項鍊中第 ii 個貝殼的種類。

第三行乙個整數 m,表示 hh 詢問的個數。

接下來 m 行,每行兩個整數 l,r,表示詢問的區間。

輸出格式

輸出 m 行,每行乙個整數,依次表示詢問對應的答案。

這個題整體思路如下:

1.將每個區間按照r進行排序。

2.新增元素進樹狀陣列,當樹狀陣列序號為r時,計算tree[r]-tree[l-1]即為區間[l,r]的種類數,之後迴圈直至輸入的r完全遍歷。

**如下:

#include

#include

#define max 1000001

int tree[max]

,pre[max]

,color[max]

,n,m;

//pre儲存第i種顏色之前的位置

typedef

struct scope

scope;

intlowbit

(int n)

void

add(

int n,

int now)

//樹狀陣列核心操作×2-->更新操作

}int

sum(

int n)

return ans;

//樹狀陣列核心操作×3-->查詢操作

}void

heapsort

(scope*

,int n)

;void

heapadjust

(scope*

,int s,

int n)

;void

swap

(scope*

,int i,

int j)

;//寫的堆排對r進行排序

intmain()

scanf

("%d"

,&m)

;for

(i =

1;i <= m;i ++

)heapsort

(range,m)

;int j =1;

for(i =

1;i <= m;i ++

) answer[range[i]

.code]

=sum

(range[i]

.r)-

sum(range[i]

.l-1);

}//***這兩個迴圈就是**的主要內容***

for(i =

1;i <= m;i ++

)return0;

}void

swap

(scope *a,

int i,

int j)

void

heapsort

(scope *a,

int n)

for(i = n;i >

1;i --)}

void

heapadjust

(scope *a,

int s,

int n)

}

**主要的兩個迴圈讓我有乙個疑問點。當我把兩個迴圈的內外關係顛倒後,就是先將資料加入tree陣列,然後當序號等於r時記錄乙個answer。我想了非常久覺得這個邏輯和文中寫的迴圈的邏輯應該是乙個意思,但是全是wa,想了兩個小時了,就此作罷。

HH的項鍊 樹狀陣列

code 我洛谷部落格 點這裡某一段貝殼中,包含了多少種不同的貝殼?最開始看見這道題時,沒有思路 但再看看,可以非常明了的發現這是乙個樹狀陣列ban題 設有一長為5的項鍊 1 2 3 2 1 然後 m 3 1 52 5 1 3我的思路是這樣,由於要求的是種類數 求l 到 r 的個數 每種貝殼只能存乙...

HH的項鍊(樹狀陣列)

由於詢問的是區間中貝殼的種類數,所以問詢區間中相同種類的貝殼只有乙個會起作用 將i位置的貝殼前一次出現的位置記作pre i 種類為x的貝殼最後一次出現的位置記作f x 類似於鄰接表的nxt和had,利用pre i f x f x i來處理pre 對於每個詢問 l,r 只有pre i 也就是說所處位置...

HH的項鍊 樹狀陣列

我csdn部落格 點這裡某一段貝殼中,包含了多少種不同的貝殼?最開始看見這道題時,沒有思路 但再看看,可以非常明了的發現這是乙個樹狀陣列ban題 設有一長為5的項鍊 1 2 3 2 1 然後 m 3 1 52 5 1 3我的思路是這樣,由於要求的是種類數 求l 到 r 的個數 每種貝殼只能存乙個 不...