實現樹狀結構 資料結構之真別多想 樹狀陣列

2021-10-14 18:04:42 字數 2916 閱讀 4319

如何理解樹狀陣列?

最下面的八個方塊就代表存入 a 中的八個數,現在都是十進位制。

他們上面的參差不齊的剩下的方塊就代表 a 的上級—— c 陣列。

很顯然看出: c2 管理的是 a1 & a2 ; c4 管理的是 a1 & a2 & a3 & a4 ; c6 管理的是 a5 & a6 ;c8 則管理全部 8 個數。

所以,如果你要算區間和的話,比如說要算 a51 ~ a91 的區間和,暴力算當然可以,那上百萬的數,那就 tle 嘍。

——————摘自

初看這些文字,你可能會想:

「啊這這這???你講這些我們怎麼聽得懂啊,這樹狀陣列是啥,咋用,我們還是懵的啊」

當然,為了解決問題而書寫演算法的話,我們不需要去理解這個結構的原理到底是啥,我們只需要知道這個東西

用在哪?

怎麼用?

就足夠了

我們都知道:

一般的普通陣列單點操作的時間複雜度的o(1)區間操作的時間複雜度是o(n)

而我們樹狀陣列的和普通陣列的區別就在於:

單點操作和區間操作的時間複雜度都是o(log n),而且

單點修改和區間操作(加、求和)都需要用函式實現

那麼這麼說我們大概能理解一點了,那就是:

一旦遇到大規模使用區間求和的問題,我們就可以考慮使用樹狀陣列。

總得來說就是三個函式:lowbit、新增函式,求和函式

lowbit

int lowbit(int x)
單點修改

void add(int x, int k) 

}

區間求和

int sum(int x) 

return ans;

}

就這??就這??啊啊,看似就這,那我們來找一道模板題做一做,深化一下理解吧。

給定乙個長度為n的整數數列,請你計算數列中的逆序對的數量。

逆序對的定義如下:對於數列的第 i 個和第 j 個元素,如果滿足 i < j 且 a[i] > a[j],則其為乙個逆序對;否則不是。

輸入

第一行包含整數n,表示數列的長度。

第二行包含 n 個整數,表示整個數列。

輸出

輸出乙個整數,表示逆序對的個數。

ps: 1≤n≤1000001≤n≤100000

6

2 3 4 5 6 1

5
「逆序對」的計算需要用到大量的區間運算,在這個時候我們的樹狀陣列就發揮了很大的用處了,

對於這道題的核心思想,即是:

用陣列的值作為下標,每次出現逆序對則給該下標對應值加一,最後求和

**如下

#include #include #include #include ​

using namespace std;

​typedef long long ll;

​const int n = 100010;

​int n;

int a[n];

int tr[n];

​int lowbit(int x)

​void add(int x, int k)

​ll sum(int x)

​int main()

printf("%lldn", ans);

return 0;

}

emmm,樣例過了,提交!

誒怎麼wa了,還是段錯誤?

看了看測試資料,原來是我們將資料當作下標,而資料的大小超過了陣列大小的限制,而且也造成了空間的冗餘,這個時候,我們想到乙個方法:

離散化,即是將物件之間的關係模糊化,在不改變資料相對大小的條件下,對資料進行相應的縮小。

什麼意思呢?

比如說:

在{ 1、 2、 99999、 3 }之間判斷逆序對和在{ 1、 2、 4、 3}之間判斷逆序對在基本流程上無差別,而如果不進行離散化,則花費了99999個空間,為了節省空間,也為了消除陣列越界的風險,我們使用離散化優化一下**。

#include #include #include #include ​

using namespace std;

​typedef long long ll;

​const int n = 100010;

​int n;

int a[n], backup[n];//backup即是離散化之後的序列

ll tr[n];

​int lowbit(int x)

​void add(int x, int k)

​ll sum(int x)

​int find(int k)

return r + 1;

}//排好序儲存進來的序列,其每個元素的對應下標就是其離散化之後的「大小」

​int main()

printf("%lldn", ans);

return 0;

}

最後,我們得到了ac!!!

希望我的拋磚引玉能引起更多的思考! (蒟蒻鞠躬)。

資料結構系列( )樹狀結構

樹 是有乙個或乙個以上的節點組成,存在乙個特殊的節點,稱為樹根。每個節點是一些資料和指標組合而成的記錄。除了樹根,其餘節點可分為n 0個互斥的集合,其中每乙個子集合本身也是一種樹狀結構,即此根節點的子樹。此外一棵合法的樹,節點間可以互相連線,但不能形成無出口的迴路。度數 每個節點所有子樹的個數。層數...

資料結構 樹狀陣列

區間資訊的維護與查詢專題 樹狀陣列 1.問題 動態連續和查詢問題。給定乙個n個元素的陣列a1,a2,an,你的任務是設計乙個資料結構,支援以下兩種操作。add x,d 操作 讓ax增加d.query l,r 計算al al 1 ar.對普通陣列進行 一次修改或 特定區間 求和,時間複雜度為o n n...

資料結構 樹狀陣列

原陣列 字首和 範圍和 原陣列更改陣列元素在求和效率較低,引入樹狀陣列 假設原陣列a 樹狀陣列c 樹狀陣列 的三種操作 1.lowbit 子葉數 二進位制最低位的1代表多少 實現 int lowbit int n 求 lowbit x returnx x 2.update a i k 假設a i 是...