先膜黑科技講義 - magolor orz
設lowbit(x)表示的是把x的二進位制只留下最低一位的1,然後lowbit(x)=x&(-x) (我也不知道為什麼)
設c[x]表示從i往前一共lowbit(x)個數的和,那麼x-lowbit(x)就是c[x]表示的範圍的前乙個數。
然後可以得到c[x]=c[x-lowbit(x)+lowbit(x)>>1]+c[x-lowbit(x)+lowbit(x)>>1+lowbit(x)>>2]+c[x-lowbit(x)+lowbit(x)>>1+lowbit(x)>>2+lowbit(x)>>3]....+c[x-1]+a[x]。
也就是說,如果將這個關係做成乙個樹,x的父親就是x+lowbit(x)(觀察一下上面的式子,很容易發現每一項都滿足)
要詢問1到x的和的話,只要一直加c[x],然後讓x-=lowbit(x)直到x=0就好了
然後要修改乙個點x的話,就一直往上修改它的父親直到x>n就可以了。
也就是說,最基本的樹狀陣列支援的是單點修改和字首和查詢,然後字首和可以很容易地做成區間和(端點減一減)。
luogu3374
1 #include2 #include3 #include4view code#define lowbit(x) ((x)&(-(x)))
5#define ll long long int
6const
int maxn=500050;7
8 inline int
rd()
11while(c>='
0'&&c<='
9') x=x*10+c-'
0',c=getchar();
12return x*neg;13}
1415
intn,m;
16ll c[maxn];
1718 inline void add(int x,int
y)21 inline ll query(int
x)24
25int
main()
34 }
也可以支援區間修改和單點查詢,只要做乙個差分,區間修改就變成了兩個端點的修改,單點查詢就變成了字首和查詢。
luogu3368
1 #include2 #include3 #include4view code#define lowbit(x) ((x)&(-(x)))
5#define ll long long int
6const
int maxn=500050;7
8 inline int
rd()
11while(c>='
0'&&c<='
9') x=x*10+c-'
0',c=getchar();
12return x*neg;13}
1415
intn,m;
16ll c[maxn];
1718 inline void add(int x,int
y)21 inline ll query(int
x)24
25int
main();
31for(i=1;i<=m;i++)
37else printf("
%lld\n
",query(b));38}
39 }
區間修改和區間查詢也是可以支援的,然後我選擇線段樹......
樹狀陣列寫起來真方便,suki
$$前n項和\sum_^=\sum_^^}(差分陣列)=\sum_^=(n+1)\sum_^-\sum_^$$
這樣的話,只要同時維護d[i]和i*d[i],就可以做到區間修改和區間查詢了。
luogu3372
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #includeview code10#define pa pair11
#define lowb(x) ((x)&(-(x)))
12#define rep(i,n0,n) for(i=n0;i<=n;i++)
13#define per(i,n0,n) for(i=n;i>=n0;i--)
14#define max(a,b) ((a>b)?a:b)
15#define min(a,b) ((a16
#define clr(a,x) memset(a,x,sizeof(a))
17#define rei register int
18using
namespace
std;
19 typedef long
long
ll;20
const
int maxn=100010;21
22ll rd()
25while(c>='
0'&&c<='
9') x=x*10+c-'
0',c=getchar();
26return x*neg;27}
2829
intn,m;
30ll tr[maxn],itr[maxn];
3132 inline void add(int
x,ll y)37}
38 inline ll query(int
x)return
re;43}44
45int
main()for(i=1;i<=m;i++)else57}
58return0;
59 }
二維的話也是可以做的,就相當於每跳到乙個x都跳一遍y的lowbit,而且可以支援區間修改和區間查詢
單點修改區間查詢不多說,來說說區間修改和查詢
仿照一維的形式,我們先得到差分陣列
因為差分陣列的字首和就是原來那個點的值,所以能得到$d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]$
所以如果是(x1,y1,x2,y2)區間加的話,就是給(x1,y1),(x2+1,y2+1)加,給(x1,y2+1),(x2+1,y1)減(手畫一下)
然後是查詢,也是有$(x1,y1,x2,y2)=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]$
然後有$$s[x][y]=\sum\limits_^^^^}}}$$
$$=\sum\limits_^^^}}$$
$$=\sum\limits_^^}$$
於是二維樹狀陣列維護d,id,jd和ijd就行了
高階用法以後慢慢填
樹狀陣列模板
假設有一列數 1 i n 支援如下兩種操作 1.將ai的值加d。2.輸出ai ai 1 aj 1 i j n 樹狀陣列是一種特殊的資料結構,這種資料結構的時空複雜度和線段樹相似,但是它的係數要小得多 hdu 1166 敵兵布陣 題目 a國在海岸線沿直線布置了n個工兵營地。由於採取了某種先進的監測手段...
樹狀陣列模板
已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數數加上x 2.求出某乙個數的和 這種水水的樹狀陣列,博主就不做介紹,直接上 希望大家可以多多捧場!include include include include include include include include include ...
樹狀陣列模板
樹狀陣列 binary indexed tree bit fenwick tree 是乙個查詢和修改複雜度都為log n 的資料結構。主要用於查詢任意兩位之間的所有元素之和,但是每次只能修改乙個元素的值 經過簡單修改可以在log n 的複雜度下進行範圍修改,但是這時只能查詢其中乙個元素的值。一,改點...