樹狀陣列 模版1和2 P3368 P3374

2022-05-27 19:36:11 字數 2371 閱讀 5982

題目描述

如題,已知乙個數列,你需要進行下面兩種操作:

將某乙個數加上 x

求出某區間每乙個數的和

輸入格式

第一行包含兩個正整數 n,m,分別表示該數列數字的個數和操作的總個數。

第二行包含 n 個用空格分隔的整數,其中第 i 個數字表示數列第 i項的初始值。

接下來 m 行每行包含

3個整數,表示乙個操作,具體如下:

1x k 含義:將第 x 個數加上 k

2x y 含義:輸出區間 [x,y]內每個數的和

輸出格式

輸出包含若干行整數,即為所有操作

2 的結果。

令這棵樹的結點編號為c1,c2...cn。令每個結點的值為這棵樹的值的總和,那麼容易發現:

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

...c16 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16

這裡有乙個有趣的性質:

設節點編號為x,那麼這個節點管轄的區間為2^k(其中k為x二進位制末尾0的個數)個元素。因為這個區間最後乙個元素必然為ax,

所以很明顯:cn = a(n – 2^k + 1) + ... + an

2.模版2

如題,已知乙個數列,你需要進行下面兩種操作:

1.將某區間每乙個數數加上x

2.求出某乙個數的值

第一行包含兩個整數n、m,分別表示該數列數字的個數和操作的總個數。

第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。

接下來m行每行包含2或4個整數,表示乙個操作,具體如下:

操作1: 格式:1 x y k 含義:將區間[x,y]內每個數加上k

操作2: 格式:2 x 含義:輸出第x個數的值

輸出包含若干行整數,即為所有操作2的結果。

因為本題不是單純修改乙個數,而是修改一段區間的數,所以fix(x,k)表示把x到最後乙個數都加上,但是我們把y+1到最後乙個數也都加上了k,而我們只需要把x到y加k,所以fix(y+1,-k)把y+1到最後乙個數都減去k,就是把多加的都減去。我們就知道了每個數所對應的修改量,把原來的數加上修改量,就是所得的數

1 #include 2 #include 3

using

namespace

std;

4long

long

n,m;

5long

long

x,y,k;

6long

long

w1;7

long

long a[500001];8

long

long s[500001];9

void fix(long

long x,long

long

v)1015}

16long

long find(long

long

x)17

23return

ret;24}

25int

main()

2632

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

3340

if (w1==2)41

45}46return0;

47 }

洛谷P3368 樹狀陣列模版2

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

P3368 模板 樹狀陣列 2

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

P3368 模板 樹狀陣列 2

題目傳送門 p3368 模板 樹狀陣列 2 給你乙個長度為n的陣列 操作 1 格式 1 x y k 含義 將區間 x,y x,y x,y 內每個數加上 kkk 操作 2 格式 2 x 含義 輸出第 x xx 個數的值。區間更新,單點查詢的樹狀陣列 include include include in...