演算法(十三)樹狀陣列

2021-08-13 00:47:18 字數 1520 閱讀 1897

問題描述

小蔥喜歡除法,所以他給了你n個數a1, a2, ⋯, an,並且希望你執行m次操作,每次操作可能有以下兩種:

給你三個數l, r, v,你需要將al, al+1, ⋯, ar之間所有v的倍數除以v。

給你兩個數l, r,你需要回答al + al+1 + ⋯ + ar的值是多少。

輸入格式

第一行兩個整數n, m,代表數的個數和操作的次數。

接下來一行n個整數,代表n個數一開始的值。

接下來m行,每行代表依次操作。每行開始有乙個整數opt。如果opt=1,那麼接下來有三個數l, r, v,代表這 次操作需要將第l個數到第r個數中v的倍數除以v;如果opt = 2,那麼接下來有兩個數l, r,代表你需要回答第l個數到第r個數的和。

輸出格式

對於每一次的第二種操作,輸出一行代表這次操作所詢問的值。

樣例輸入

5 3

1 2 3 4 5

2 1 5

1 1 3 2

2 1 5

樣例輸出

15

14

評測用例規模與約定

對於30%的評測用例,1 ≤ n, m ≤ 1000;

對於另外20%的評測用例,第一種操作中一定有l = r;

對於另外20%的評測用例,第一種操作中一定有l = 1 , r = n;

對於100%的評測用例,1 ≤ n, m ≤ 105,0 ≤ a1, a2, ⋯, an ≤ 106, 1 ≤ v ≤ 106, 1 ≤ l ≤ r ≤ n。

採用最常規的方法解題,**如下:

#include

using

namespace

std;

int main()

}else

if (choose == 2)

}return

0;}

這樣的方法可以成功解決問題,但是時間複雜度過高,通過使用樹狀陣列的方式,可以降低時間複雜度。

樹狀陣列的思想可參考部落格:搞懂樹狀陣列

**實現如下,update函式實際上是乙個add函式,預設初始時tree和a陣列的元素值都是0,然後每次輸入乙個元素,將其作為新增量傳給update函式。update函式會更改有變動的所有tree元素值。getsum函式是求和函式,但是並不作用與a陣列,而是作用於tree陣列,在這裡減少了時間複雜度。:

#include 

long

long tree[101024];

int n, m, a[101024];

void update(int i, int val)

}long

long getsum(int i)

return sum;

}int main()

for (int i = 1; i <= m; ++i)

++l;}}

}return

0;}

演算法 樹狀陣列

演算法適用於求前k個整數的和,一般的做法是設定乙個sum陣列來表示 1 問題公升級一下 在查詢的過程中隨時給第x個整數加上乙個整數v,同樣要求查詢第k個整數的和。此時若還是原來的sum陣列,則要遍歷來更新,複雜度為o n 而用樹狀陣列則時間要更快。2 再來一題 很簡單的,別怕昂 計算序列中在元素左邊...

演算法 樹狀陣列

相信大家都會樹狀陣列的 單點修改,區間查詢 或者 區間修改,單點查詢 博主就不細講了。但是博主今天發現了乙個神奇的演算法 博主太菜 它可以使用樹狀陣列維護 區間修改,區間查詢 就是乙個優化過的字首和,使查詢和修改協調為 theta log 2n namespace fentree void add ...

演算法 樹狀陣列

要學樹狀陣列的先看懂一幅圖 這就是樹狀陣列的儲存方式。那麼樹狀陣列的優點是什麼呢,允許任意修改,可快速提取出a陣列內數字 據圖可知 c1 a1,c2 a1 a2,c3 a3,c4 a1 a2 a3 a4,c5 a5,c6 a5 a6,c7 a7,c8 a1 a2 a3 a4 a5 a6 a7 a8,...