洛谷 P3374 樹狀陣列 模板1

2021-08-15 19:22:26 字數 2130 閱讀 6165

樹狀陣列是將每個元素加到他後面的元素上,每次向後走lowbit(x)位,樹狀陣列中存的是該位之前的字首和,所以求某個區間和時只需要將區間兩個端點的字首和相減即可,但是如果直接暴力求字首和一定會t,所以要引入乙個新東西 ->lowbit

引用大佬的話:

我先說個叫lowbit的東西,lowbit(k)就是把k的二進位制的高位1全部清空,只留下最低位的1,比如10的二進位制是1010,則lowbit(k)=lowbit(1010)=0010(2進製),介於這個lowbit在下面會經常用到,這裡給乙個非常方便的實現方式,比較普遍的方法lowbit(k)=k&-k,這是位運算,我們知道乙個數加乙個負號是把這個數的二進位製取反+1,如-10的二進位制就是-1010=0101+1=0110,然後用1010&0110,答案就是0010了!明白了求解lowbit的方法就可以了,繼續下面。介於下面討論十進位制已經沒有意義(這個世界本來就是二進位制的,人非要主觀的構建乙個十進位制),下面所有的數沒有特別說明都當作二進位制。   

上面那麼多文字說lowbit,還沒說它的用處呢,它就是為了聯絡a陣列和c陣列的!ck表示從ak開始往左連續求lowbit(k)個數的和,比如c[0110]=a[0110]+a[0101],就是從110開始計算了0010個數的和,因為lowbit(0110)=0010,可以看到其實只有低位的1起作用,因為很顯然可以寫出c[0010]=a[0010]+a[0001],這就為什麼我們任何數都只關心它的lowbit,因為高位不起作用(基於我們的二分規則它必須如此!),除非除了高位其餘位都是0,這時本身就是lowbit。

既然關係建立好了,看看如何實現a某乙個位置資料跟改的,她不會直接改的(開始就說了,a根本不存在),她每次改其實都要維護c陣列應有的性質,因為後面求和要用到。而維護也很簡單,比如更改了a[0011],我們接著要修改c[0011],c[0100],c[1000],這是很容易從圖上看出來的,但是你可能會問,他們之間有申明必然聯絡嗎?每次求解總不能總要拿圖來看吧?其實從0011——>0100——>1000的變化都是進行「去尾」操作,又是自己造的詞--'',我來解釋下,就是把尾部應該去掉的1都去掉轉而換到更高位的1,記住每次變換都要有乙個高位的1產生,所以0100是不能變換到0101的,因為沒有新的高位1產生,這個變換過程恰好是可以借助我們的lowbit進行的,k +=lowbit(k)。

好吧,現在更新的次序都有了,可能又會產生新的疑問了:為什麼它非要是這種關係啊?這就要追究到之前我們說c8可以看作a1~a8的左半邊和+右半邊和……的內容了,為什麼c[0011]會影響到c[0100]而不會影響到c[0101],這就是之前說的c[0100]的求解實際上是這樣分段的區間 c[0001]~c[0001] 和區間c[0011]~c[0011]的和,數字太小,可能這樣不太理解,在比如c[0100]會影響c[1000],為什麼呢?因為c[1000]可以看作0001~0100的和加上0101~1000的和,但是0101位置的數變化並會直接作用於c[1000],因為它的尾部1不能一下在跳兩級在產生兩次高位1,是通過c[0110]間接影響的,但是,c[0100]卻可以跳一級產生一次高位1。

不懂的話自己去手模,再畫個樹狀圖模擬陣列中存的值,大概就理解得差不多了

要記得   lowbit(x)=x & -x

upfate 19-8-22:這份**太醜了,去看我改過的吧模板2

**

//by acer.mo

#include#includeusing namespace std;

const int maxa=10000000;

int a[maxa+10]=;//初始的儲存陣列

int l_b[maxa+10]=;//樹狀陣列

int n,i,j,m;

int lowbit(int x)//求x的lowbit值

void add(int k,int num)//lowb丟值函式 /構建樹形 /後期單點加值

int query(int x)//求和函式,求第x位前的和

return sum;

}int main()

int s,a,b;

while (m--)

else

}return 0;

}

洛谷P3374 模板 樹狀陣列1

如題,已知乙個數列,你需要進行下面兩種操作 1.將某乙個數加上x 2.求出某區間每乙個數的和第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個整數,表示乙個操作,具體如下 操作1 格式 1...

洛谷P3374 模板 樹狀陣列 1

題目描述 如題,已知乙個數列,你需要進行下面兩種操作 1.將某乙個數加上x 2.求出某區間每乙個數的和 輸入輸出格式 輸入格式 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個整數,表示...

洛谷 P3374 模板 樹狀陣列 1

題目描述 如題,已知乙個數列,你需要進行下面兩種操作 1.將某乙個數加上x 2.求出某區間每乙個數的和 輸入輸出格式 輸入格式 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3個整數,表示乙個...