1. 程式人生 > >算法基礎-樹狀數組

算法基礎-樹狀數組

emma size div from 前綴和 urn rom 效率 [1]

今天我們分享一下樹狀數組,前置知識-了解樹的結構,知道什麽是左右兒子,各個節點的名稱,也就是有點基礎吧。今天以一個實際問題引出樹狀數組吧,中查詢l-r的區間。(以B站大佬的課件為例子,可以關註下,在最後放上鏈接)

技術分享圖片

如果是暴力的話,顯然時間復雜度是接受不了的(o(n方)),為了解決這個問題,我們就要用一些高級的數據結構。就是我們今天介紹的樹狀數組。

首先看下樹狀數組是什麽,

樹狀數組(Binary Indexed Tree(B.I.T), Fenwick Tree)是一個查詢和修改復雜度都為log(n)的數據結構。主要用於查詢任意兩位之間的所有元素之和,但是每次只能修改一個元素的值;經過簡單修改可以在log(n)的復雜度下進行範圍修改,但是這時只能查詢其中一個元素的值(如果加入多個輔助數組則可以實現區間修改與區間查詢)。 這種數據結構(算法)並沒有C++和Java的庫支持,需要自己手動實現。在Competitive Programming的競賽中被廣泛的使用。樹狀數組和線段樹很像,但能用樹狀數組解決的問題,基本上都能用線段樹解決,而線段樹能解決的樹狀數組不一定能解決。相比較而言,樹狀數組效率要高很多。(百度上的) 然後在介紹前綴和,b[1] = a[1],b[2] = a[1] + a[2],b[3] = a[1] + a[2] +a[3]........b[n] = a[1] + a[2] + a[3] + ..... + a[n].這就是前綴和的概念,其實樹狀數組就是在維護一個前綴和。 再介紹lowbit函數,用於再左右兒子或者是父節點,偽代碼為 return x & (-x),就是返回某個數二進制從右往左的第一個一所代表的數,x於lowbit函數的關系如下、 技術分享圖片

一個左兒子的父節點表示為x + lowbit(x),同理右兒子的父親表示為 x - lowbit(x),把圖畫出來,是不是很像二叉搜索樹,
技術分享圖片

最後,給個樹狀數組的模板題吧,

如題,已知一個數列,你需要進行下面兩種操作:

1.將某區間每一個數加上x

2.求出某區間每一個數的和

輸入輸出格式

輸入格式:

第一行包含兩個整數N、M,分別表示該數列數字的個數和操作的總個數。

第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。

接下來M行每行包含3或4個整數,表示一個操作,具體如下:

操作1: 格式:1 x y k 含義:將區間[x,y]內每個數加上k

操作2: 格式:2 x y 含義:輸出區間[x,y]內每個數的和

輸出格式:

輸出包含若幹行整數,即為所有操作2的結果。(洛谷的題,https://www.luogu.org/problemnew/show/P3372)

輸入樣例

5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4

輸出樣例

11
8
20

附上AC代碼

#include<iostream>
#include<cstring>
#include<algorithm>
using
namespace std; const int N = 1e7 + 5; int n,m,a; int d[N]; //存前綴和的數組 int lowbit(int x) { return x & (-x); } int query(int x) //查詢操作 { int res = 0; while(x) //x > 0,x從左邊找父親節點相加 { res += d[x]; x -= lowbit(x); } return res; } void add(int x,int val) { while(x <= n) { d[x] += val; x += lowbit(x); //從左到右構建樹狀數組 } } int sum(int x) { int total = 0; while(x != 0) { total += d[x]; x -= lowbit(x); } return total; } int main() { cin >> n >> m; for(int i = 1;i <= n;i++) { cin >> a; add(i,a); } while(m--) { int f,x,y; cin >> f >> x >> y; if(f == 1) { add(x,y); } if(f == 2) { cout << sum(y) - sum(x - 1) << endl; } } return 0; }

最後的最後附上B站大佬的鏈接,https://www.bilibili.com/video/av36663299?from=search&seid=7911780148837730858

算法基礎-樹狀數組