1.什麼是樹狀陣列?
顧名思義,就是用陣列來模擬樹形結構唄。那麼衍生出乙個問題,為什麼不直接建樹?答案是沒必要,因為樹狀陣列能處理的問題就沒必要建樹。和trie樹的構造方式有類似之處。
2.樹狀陣列可以解決什麼問題
可以解決大部分基於區間上的更新以及求和問題。
3.樹狀陣列和線段樹的區別在**
樹狀陣列可以解決的問題都可以用線段樹解決,這兩者的區別在**呢?樹狀陣列的係數要少很多,就比如字串模擬大數可以解決大數問題,也可以解決1+1的問題,但沒人會在1+1的問題上用大數模擬。
4.樹狀陣列的優點和缺點
修改和查詢的複雜度都是o(logn),而且相比線段樹係數要少很多,比傳統陣列要快,而且容易寫。
缺點是遇到複雜的區間問題還是不能解決,功能還是有限。『
樹狀陣列結構
黑色陣列代表原來的陣列(下面用a[i]代替),紅色結構代表我們的樹狀陣列(下面用c[i]代替),發現沒有,每個位置只有乙個方框,令每個位置存的就是子節點的值的和,則有
c[1] = a[1];
c[2] = a[1] + a[2];
c[3] = a[3];
c[4] = a[1] + a[2] + a[3] + a[4];
c[5] = a[5];
c[6] = a[5] + a[6];
c[7] = a[7];
c[8] = a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8];
可以發現,這顆樹是有規律的
c[i] = a[i - 2^k+1] + a[i - 2^k+2] + … + a[i]; //k為i的二進位制中從最低位到高位連續零的長度
例如i = 8(1000)時候,k = 3,可自行驗證。
這個怎麼實現求和呢,比如我們要找前7項和,那麼應該是sum = c[7] + c[6] + c[4];
而根據上面的式子,容易的出sumi = c[i] + c[i-2^k1] + c[(i - 2^k1) - 2^k2] + …;
2^k = x&(-x),此處是用的負數的儲存特性。
x&(-x)就是求x的二進位制從低到高最近乙個1的位置。例如8(1000),lowbit(8) = 4, 7(111),lowbit(7) = 1, 4(100), lowbit(4)=3。
其實樹狀陣列就是乙個二進位制上面的應用。
建立最基本的樹狀陣列
#include#include#include#includeusing namespace std;
int n;
int a[1005], c[1005];
int lowbit(int x)
int updata(int i, int k)
}int getsum(int i)
return res;
}int main()
for(int i = 0; i <= n; i++)
cout << endl;
for(int i = 0; i <= n; i++)
cout << endl;
return 0;
}
樹狀陣列與差分結合
求在某些個區間被加k,或者減k後某一點的值
1 int n,m;
2 int a[50005] = ,c[50005]; //對應原陣列和樹狀陣列
3 4 int lowbit(int x)
7 8 void updata(int i,int k)
13 }
14 15 int getsum(int i)
21 return res;
22 }
23 24 int main()
32
33 //[x,y]區間內加上k
34 updata(x,k); //a[x] - a[x-1]增加k
35 updata(y+1,-k); //a[y+1] - a[y]減少k
36
37 //查詢i位置的值
38 int sum = getsum(i);
39 40 return 0;
41 }
維護兩個數狀陣列,sum1[i] = d[i],sum2[i] = d[i]*(i-1);
int n,m;
int a[50005] = ;
int sum1[50005]; //(d[1] + d[2] + ... + d[n])
int sum2[50005]; //(1*d[1] + 2*d[2] + ... + n*d[n])
int lowbit(int x)
void updata(int i,int k)
}int getsum(int i)
return res;
}int main()
//[x,y]區間內加上k
updata(x,k); //a[x] - a[x-1]增加k
updata(y+1,-k); //a[y+1] - a[y]減少k
//求[x,y]區間和
int sum = getsum(y) - getsum(x-1);
return 0;
}
差分樹狀陣列
一 假設現在有乙個原陣列a 假設a 0 0 有乙個陣列d,d i a i a i 1 那麼 a i d 1 d 2 d i d陣列就是差分陣列 所以求a i 就可以用樹狀陣列維護d i 的字首和 即維護的是d i 的樹狀陣列 上面的數學思想可以實現區間修改,以及單點查詢。下附上 區間修改 1 n v...
差分 差分陣列 樹狀差分
原陣列 ai94 759差分陣列 bi9 5 3 24差分陣列的字首和94 759顯然通過求字首和可以做到單點查詢 他高效的地方在於區間修改,比如我們對區間 2,4 每個元素加上5,我們只需在差分陣列 b2 5,b5 5,然後求字首和即可 原陣列 ai94 759差分陣列 bi 903 2 1 差分...
差分詳解 樹狀陣列擴充套件
前言 現在還不是很懂,不過先把模板抄在這裡把。介紹一下差分,乙個很簡單的東西。一 簡介 已知陣列a為1,2,1,5,7,4 那麼差分陣列1,1,1,4,2,3 顯然,差分陣列就是當前項與前一項的差值。容易得到,an就是差分陣列的前n項和。二 那麼有什麼便利的地方呢?我們假想一下,現在要給1至4的區間...