一天一道演算法題 樹狀陣列

2022-05-06 17:30:17 字數 1915 閱讀 2860

題目【模板】樹狀陣列1:

樹狀陣列和線段樹差不多,可以處理區間操作,但是處理不了太複雜的區間問題。,不過**比線段樹簡潔很多很多!!!時間複雜度都為o(logn)。

例如,區間[1,8]儲存方式如下:

1 tree[1]=num[1];//

001---001

2 tree[2]=num[2]+num[1];//

010---010 001

3 tree[3]=num[3];//

011---011

4 tree[4]=num[4]+num[3]+num[2]+num[1];//

100---100 011 010 001

5 tree[5]=num[5];//

101---101

6 tree[6]=num[6]+num[5];//

110---110 101

7 tree[7]=num[7];//

111---111

8 tree[8]=num[8]+num[7]+num[6]+num[5]+num[4]+num[3]+num[2]+num[1];///

1000---1000 0111 0110 0101 0100 0011 0010 0001

從注釋可以看出儲存方式和二進位制有關係。

遞推可得,當第x個數加上k時,tree[x]要加k,然後tree[x+x只剩最低位的1]也要加上x,迴圈往復。

根據負數在計算機中用補碼儲存可得k & -k即為x只剩最低位的1。

如7&-7

7用二進位制表示為111,-7補碼形式為001,111&001得001,所以7只剩最低位的1為001.

ac**:

#include#include

#include

#define maxn 500010typedef

long

long

ll;using

namespace

std;

intn;

ll tree[maxn

<< 2

];int lowbit(int

k) void add(int

x, ll k)

}ll sum(

intx)

return

ans;

}int

main()

while (m--)

else

}return0;

}

view code

o(∩_∩)o哈哈~

補充一道區間加k的操作。

用差分思想和樹狀陣列結合。

設陣列a=,那麼差分陣列b=

也就是說b[i]=a[i]-a[i-1];(a[0]=0;),則遞推可得:a[i]=b[1]+....+b[i]

所以對區間[x,y]進行修改,只用修改b[x]與b[y+1]:

b[x]=b[x]+k;b[y+1]=b[y+1]-k;

#include#include

#include

#define maxn 500010typedef

long

long

ll;using

namespace

std;

intn,a[maxn];

ll tree[maxn

<< 2

];int lowbit(int

k) void add(int

x, ll k)

}ll sum(

intx)

return

ans;

}int

main()

while (m--)

else

}return0;

}

view code

\(^o^)/~

一天一道演算法題 線段樹

題目 模板 線段樹1 rmq問題 range minimum maximum query 和求區間和的問題可以用暴力法做,時間複雜度為o n 2 用在本題會超時,所以我們選擇線段樹做。線段樹是一種用於區間操作的資料結構,用二叉樹構造。如圖。線段樹的每個節點代表了乙個區間。防止超時,用了lazy標記。...

一天一道演算法題 5 24 遞迴

我們每一天都應該比昨天更強一點 觀察下列式子 12 12 1 12 6 2 12 4 3 12 3 4 12 3 2 2 12 2 6 12 2 3 2 12 2 2 3 對於給定的n 計算n公有多少種不同的分解式?1 include 2 using namespace std 34 int cnt...

一天一道演算法題 之動態規劃

最近做了幾道動態規劃題,發現了其中一些規律,認真覆盤一下。先來看幾道題。1 機械人走方格 有乙個xxy的網格,乙個機械人只能走格點且只能向右或向下走,要從左上角走到右下角。請設計乙個演算法,計算機械人有多少種走法。注意網格中有些障礙點是不能走的。給定乙個intmap c 中為vector 表示網格圖...