樹狀陣列及二維樹狀陣列

2022-02-24 16:53:36 字數 2584 閱讀 7144

一直以為樹狀陣列能用線段樹水過去,直到我今天碰上了樹狀陣列模板題。

然後就是開始認真的學習樹狀陣列,突然發現怎麼這麼好寫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函式的**

1

int lowbit(intk)2

lowbit

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 是第三行...