一直以為樹狀陣列能用線段樹水過去,直到我今天碰上了樹狀陣列模板題。
然後就是開始認真的學習樹狀陣列,突然發現怎麼這麼好寫qwqqqq。
部分**
一.樹狀陣列
樹狀陣列是一種資料結構,核心思想是利用二進位制的補碼思想。
首先就是樹狀陣列的結構圖
然後我們對他進行變形
是不是感覺更好理解了呢?
然後我們對其進行標號
c陣列表示的是記錄的值,a陣列表示的是原序列。然後就是所有關於樹狀陣列的部落格都會有的c陣列的存值的展示,博主較懶就不寫了,具體看推薦部落格。
最重要的性質是
c[i]=a[i-2^k+1]+a[i-2^k+2]+......a[i]; (k為i的二進位制中從最低位到高位連續零的長度)
上面說k是二進位制中最低位到最高位的連續零的長度也就是6的二進位制是110,那麼k就是1,然後我們帶入:
c[6]=a[6-2+1]+a[6-2+2]=a[5]+a[6]
看,是不是與上方式子相符,這就是lowbit要實現的功能。那麼,lowbit實現的原理是啥呢?
先粘一下lowbit函式的**
1lowbitint lowbit(intk)2
k&(-k)是啥意思呢?
然後你就會發現,你能夠取出最小一位的1,而在上面的例子中就是2,你可以再用幾組資料試一下,發現lowbit(i)=2^i。
4(0100),反碼4(0011),補碼(0100),0100&0100=0100,則lowbit(i)=4,又根據連續0的位數,則k=2,2^2=4,則假設成立。
所以,是不是非常的明白了?
其實還有一種lowbit的寫法,k&(k^(k-1)),可以自己手推一下。
然後就是單點修改,**
1單點修改void add(int x,int
val)
28 }
為啥是i<=n呢?因為你單點修改是要從葉子結點蹦向父節點的,所以要從小到大。
1區間查詢int sum(intx)2
9return
ans;
10 }
那為啥區間查詢是i!=0呢?因為區間查詢是從父節點蹦向子節點的,所以i要不斷減小,記住區間查詢是查詢的字首和,所以要查[l,r]的話需要sum(r)-sum(l-1)。
會了以上操作,就先做一下模板題吧p3374 【模板】樹狀陣列 1、
如果我們想區間修改呢?你該不會是列舉然後add(i)吧,不t才怪啊!
這時我們就用到了一種新的思想,差分思想。差分思想是很常見的,下面介紹一下:
陣列a=,那麼差分陣列b=
也就是說b[i]=a[i]-a[i-1];(a[0]=0;),那麼a[i]=b[1]+....+b[i];(這個很好證的)。
假如區間[2,4]都加上2的話
a陣列變為a=,b陣列變為b=;
發現了沒有,b陣列只有b[2]和b[5]變了,因為區間[2,4]是同時加上2的,所以在區間內b[i]-b[i-1]是不變的.
所以對區間[x,y]進行修改,只用修改b[x]與b[y+1]:
b[x]=b[x]+k;b[y+1]=b[y+1]-k;
所以,我們在存的時候就存差分陣列,然後我們只改變l,與r+1的值,就好了。
那麼單點查詢呢?別忘了樹狀陣列存的是字首和!我們直接sum(a)。
那差分下的區間查詢呢?直接原數列a[r]-a[l-1]!
二.二維樹狀陣列
二維樹狀陣列,就是矩陣嘛!你按照矩陣的方式做不就好了!
在add和sum函式裡,兩層迴圈,一層y一層x,不就好了!
然後就是二位樹狀陣列所有的**演示
#include#include二維樹狀陣列#include
#include
#include
using
namespace
std;
int a[2000][2000
],n;
int lowbit(int
k)void change(int i,int
y) i+=lowbit(i);
}}int ask(int i,int
y) i-=lowbit(i);
}return
ans;
}int
main()
else
}printf("\n
");}
}
樹狀陣列及二維樹狀陣列
樹狀陣列或者二叉索引樹也稱作binary indexed tree,又叫做fenwick樹 它的查詢和修改的時間複雜度都是log n 空間複雜度則為o n 這是因為樹狀陣列通過將線性結構轉化成樹狀結構,從而進行跳躍式掃瞄。通常使用在高效的計算數列的字首和,區間和。為什麼要用樹狀陣列 線段樹比樹狀陣列...
樹狀陣列 二維樹狀陣列模板
樹狀陣列模板 int lowbit int x int add int x,int val int que int x 模板題 題解 include include include using namespace std int c 300000 rank 300000 int n int lowb...
樹狀陣列 二維
首先初始陣列還是a陣列,二維的 搞乙個b陣列,也是二維,b i 就是a陣列第i行的一維樹狀陣列 b 2 1 a 2 1 b 2 2 a 2 1 a 2 2 b 2 3 a 2 3 最後我們來搞乙個c陣列,當然它還是二維的hhh c 1 就是第一行的樹狀陣列,c 2 是第一行加第二行,c 3 是第三行...