如何理解樹狀陣列?
最下面的八個方塊就代表存入 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 是...