前言:遇到二維的問題都很虛,而且樹狀陣列也不熟練……於是學了一發這個。
以下所有問題均在二維中
1.單點修改,單點查詢
這個最簡單,直接開乙個二維陣列搞一搞就完事了。
2.單點修改,區間查詢
$ans=sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1)$
**:
inline void add(int x,int y,intk)inline
int sum(int x,int
y)
3.區間修改,單點查詢
回想一下一維的樹狀陣列是怎麼維護的:我們維護$a[i]$的差分陣列$d[i]$;讓區間$[l,r]$加$k$就讓$d[l]$加$k$,$d[r+1]$減$k$。求和就是$a[i]=\sum\limits_^i d[j]$。放到二維也是一樣,差分陣列的意義變成如下:
$d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]$(模擬二維字首和)
比如我們想讓$(2,2,3,4)$之間的部分加$1$:
原先是這樣的:
0000000
0000
0000
0000
0
做一下差分:
0000001
00 -100
0000 -100
1
**:
inline void add(int x,int y,intk)inline
int sum(int x,int
y)inline
void update(int x1,int y1,int x2,in
y2)
4.區間修改,區間查詢
這個我一維樹狀陣列也沒幹過這個,都是拿線段樹寫的……直接推式子吧。
我們還是維護差分陣列。想求$(1,1,x,y)$內所有數和,我們有:
$ans=\sum\limits_^x \sum\limits_^y \sum\limits_^i \sum\limits_^j d[k][h]$
考慮每個$d$算了多少次,我們可以化簡得到:
$ans=\sum\limits_^x \sum\limits_^y d[i][j]*(x-i+1)*(y-j+1)$\
$ans=(x+1)*(y+1)\sum\limits_^x \sum\limits_^y d[i][j]-(x+1)\sum\limits_^x \sum\limits_^y d[i][j]*j-(y+1)*\sum\limits_^x \sum\limits_^y d[i][j]*i+\sum\limits_^x \sum\limits_^y d[i][j]*i*j$
然後用四個樹狀陣列分別維護一下就行了。
**:
inline void add(int x,int y,intz)inline
int sum(int x,int
y)
二維樹狀陣列學習筆記
1首先從一維的開始,考慮最基礎的單點修改,區間查詢。樹狀陣列模板1 這個是最基礎的,就是定義的應用。2再考慮區間修改,單點查詢。樹狀陣列模板2。我們可以想到,在對一段區間 l,r 進行修改時,可以將 1,r 加上 k 將 1,l 1 減去 k 但這樣修改,對於單點查詢來說,似乎不是那麼的方便,我們可...
樹狀陣列 二維
首先初始陣列還是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 是第三行...
二維樹狀陣列
什麼是二維樹狀陣列 二維樹狀陣列 單點修改,區間查詢 include const int maxn 4096 5 typedef long long ll ll c maxn maxn int n,m int lowbit int x void modify int x,int y,int z ll...