P3368 模板 樹狀陣列 2

2021-09-29 15:35:14 字數 1564 閱讀 2722

題目描述

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

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

2.求出某乙個數的值

輸入格式

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

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

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

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

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

輸出格式

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

輸入輸出樣例

輸入 #1 複製

5 51 5 4 2 3

1 2 4 2

2 31 1 5 -1

1 3 5 7

2 4輸出 #1 複製610

emmmm,本來就笨,時間複雜度我幾乎沒怎麼算過,一開始我以為和模板1一樣,這題又多了乙個技巧,差分,這些技巧都是優化時間複雜度的,因為再數很大的情況,很容易**,這裡我就說一下我的理解,說的不太好

在模板1的理解的基礎上,這裡多乙個差分,這是在模板以上的乙個拓展,大意是用差分陣列的前i項和來表示a[i],這題主要使用樹狀陣列來維護差分陣列,什麼叫差分呢

設陣列a=,那麼差分陣列b=,b[i] = a[i] -a[i-1],這裡a[0]=0;

容易推得a[i] = b[1]+…b[i], 如果從 2-4都+2,那麼b=,只有b[2],b[4]分別+2,-2,這裡也很容易理解,也就是說區間數值變化,而差分陣列只要改變2端點就可以了,這極大的縮短了時間,從o(p n)->o(p logn)(別問我= =),所以,綜上,在區間上的變化,可以等於在差分陣列的端點變化,假如[l,r]區間都加上k,只要b[l]+k,b[r]-k就可以了,

那麼怎麼求a[i]呢,集合模板1一樣,根據二進位制的性質,一點一點加差分陣列就可以了

#include

#include

#include

const

int n =

5e6+5;

using

namespace std;

int n,m;

long

long c[n]

,sz[n]

;int

lowbit

(int x)

void

add(

int x,

long

long k)

}long

long

sum(

int x)

return ans;

}int

main()

int x,y,z;

long

long k;

for(

int i=

1;i<=m;i++

)else

if( x ==2)

}return0;

}

自己理解的還不是透徹,估計明天又得忘,線段樹的模板今天也沒弄,淦,效率低,理解又差(┭┮﹏┭┮)

洛谷上超詳細

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...

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個整數,表示乙個操作,具體如下 操作1 格式...