題目描述
如題,已知乙個數列,你需要進行下面兩種操作:
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 格式...