树状数组基础原理与模板
樹狀數組
2021年7月29
1、算法原理
樹狀數組解決什么問題?
解決區間上點更新與維護的問題。如更改某些點值求區間和,或求某位前有多少比其小的問題。
其實現的原理是什么?
首先看圖:
在這個圖中,將每1<<i個數(0<=i<=n)分為一組 ,此時設置函數lowbit(i),此函數將i的2進制中最后一位1前的數字全部刪去,如lowbit(6)=4。
由圖可看出,對于每個i,其都存在在其本身與i+lowbit(i)的區間數組內。例如:5—>101,101+1=110,此時存在于下標為6的區間內,隨后,110+10=1000,1000+1000=10000,因此,5同時存在于下標為8與下標為16的區間內。
由此,可對數組進行更新操作:
for( ;i <= n; i+=lowbit(i)){tre[i]+=1;//此處不一定為1,根據題目不同更改,先對應下面樣例 }對于最大值為n的樹狀數組,每次將i加入相應區間。
那么,怎么進行查詢操作?
對于一個數i可知,小于等于其本身的數字一定都存在于比其下標更小的數組里。因此此處依然可以按照二進制位進行查詢,為了避免重復查詢,依次進行i-lowbir(i)的操作進行查詢,如:11—>1011,1011-1=1010,1010-10=1000,1000-1000=0(若下標從1開始可不要),此時查詢的下標為10,8,由圖可知,所有小于等于11的數字,均存在于下標為10和8的數組內。
因此有查詢操作:
for( ; i > 0; i-=lowbit(i)){res+=tre[i]; }2、模板題:
描述:
第一行輸入一個n,接下來一行輸入n個數,為a1…an,1<=ai<=1e4。
接下來一行輸出n個數,對于每個ai,輸出其之前比它小的數字的數量。
#include<iostream> #include<algorithm> #include<stdio.h>using namespace std;int n,num; int tre[1005],ans[1005];int lowbit(int i){return (i & -i); }void settre(int i){for( ; i < 1005; i += lowbit(i)){tre[i]++;} }int solvetre(int i){int res = 0;for( ; i; i -= lowbit(i)){res+=tre[i];}return res; }int main(){cin>>n;for(int i = 1; i <= n; i++){cin>>num;ans[i]=solvetre(num-1);settre(num);}cout<<ans[1];for(int i = 2; i <= n; i++){cout<<' '<<ans[i];}cout<<'\n';return 0; }輸入樣例:
9 1 5 2 9 4 1 7 8 3輸出樣例:
0 1 1 3 2 0 5 6 33、實操例題
ACwing 242. 一個簡單的整數問題
分析:
本題應將第i個數的差分存入樹狀數組,以便查詢。
AC代碼:
#include<iostream> #include<algorithm> #include<stdio.h> #include<string> #include<string.h> typedef long long ll;using namespace std;int n, m, num; int a, b; ll tre[100005]; int sic[100005]; string k;ll lowbit(ll i) {return (i & -i); }void settre(int i, int c) {for (; i < n + 1; i += lowbit(i)) {tre[i] += c;} }ll solvetre(int i) {ll res = 0;for (; i; i -= lowbit(i)) {res += tre[i];}return res; }int main() {cin >> n >> m;for (int i = 1; i <= n; i++) {cin >> sic[i];}for (int i = 1; i <= n; i++) {settre(i, sic[i] - sic[i - 1]);}while(m--){cin >> k;if (k == "Q") {cin >> num;cout << solvetre(num) << endl;}else {cin >> a >> b >> num;settre(a, num); settre(b + 1, -num);}}return 0; }總結
以上是生活随笔為你收集整理的树状数组基础原理与模板的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ctrl c 失效了怎么办
- 下一篇: 线段树-简单线段树模板