差分陣列 定義 使用方法 與線段樹的區別

2021-09-26 02:15:06 字數 2633 閱讀 3976

1.定義

對於乙個有n個元素的陣列a[n],我們令a[i]-a[i-1]=d[i],且d[1]=a[1]-0=a[1];那麼我們將d[i]稱為差分陣列—即記錄陣列中的每項元素與前一項的差值

2.性質

(1)計算陣列a各項的值(陣列下標從1開始,a[0]=0)

例如a[3]=d[3]+d[2]+d[1]

=(a[3]-a[2])+(a[2]-a[1])+(a[1]-a[0])

=a[3]

(2)統計d陣列的字首和sum陣列

什麼是字首和?字首和顧名思義就是前面i個數的總和

sum[i]=d[1]+d[2]+…d[i]=a[1]+a[2]-a[1]+…a[i]-a[i-1]=a[i];

3.用法

(1)快速處理區間加減操作

每次在區間[l,r]增減x只需要令d[l]+x,d[r+1]-x,就可以保證[l,r]增加了x,而對[1,l-1]和[r+1,n]無影響。複雜度則是o(n)的。這樣我們不必對區間內每乙個數進行處理,只需處理兩個差分後的數即可.

現在我們令區間[2,4]的元素都+2,那麼第乙個受影響的差分陣列中的元素為d[2],因為d[2]=a[2]-a[1],a[2]是區間內第乙個變化的元素,所以第乙個受影響的差分陣列元素是d[2],同理最後乙個受影響的是d[5],即d[r+1](你看a[4]+2,d[5]=a[5]-a[4]的值變小了)

我們令d[2]+2,令d[5]-2,就相當於對整個區間的元素進行了+2操作,避免了對陣列a所有元素進行操作。那麼為什麼不用對差分陣列d[3],d[4]進行修改呢,因為區間內的元素同時都加上同樣的數字,所以d[3],d[4]計算後仍然是不變的

那麼我們就可以得到a[2]=sum[2]=d[1]+d[2]=4;a[4]=sum[4]=1+3+1+1=6;a[5]=sum[5]=1+3+1+1-1=5;

(2)詢問區間和問題

區間[l,r]的和為sum[r]-sum[l-1];

ps:這裡的sum陣列和前面的差分陣列的字首和陣列不是乙個東西,這裡代表區間和,例如sum[3]=a[1]+a[2]+a[3]

4.和線段樹的區別

差分陣列:

更新時間複雜度 o(1)

查詢時間複雜度 o(n)

線段樹 :

更新時間複雜度 o(logn)

查詢時間複雜度 o(logn)

建樹時間複雜度o(n)

因此,差分陣列適用於多次更新,常量次查詢,資料範圍在1e7以內的情況;線段樹適用於多次更新,多次查詢,資料範圍在1e5以內的情況。

下面例題的要求比較低,兩種資料結構都可以用。

but如果改動一下要求:

1、資料範圍不是1e5而是1e7,只能用差分陣列。

2、不是一次查詢而是多次查詢,只能用線段樹。

color the ball hdu - 1556

問題描述:

n個氣球排成一排,從左到右依次編號為1,2,3…n.每次給定2個整數a b(a <= b),lele便為騎上他的「小飛鴿"牌電動車從氣球a開始到氣球b依次給每個氣球塗一次顏色。但是n次以後lele已經忘記了第i個氣球已經塗過幾次顏色了,你能幫他算出每個氣球被塗過幾次顏色嗎?

每個測試例項第一行為乙個整數n,(n <= 100000).接下來的n行,每行包括2個整數a b(1 <= a <= b <= n)。

當n = 0,輸入結束。

每個測試例項輸出一行,包括n個整數,第i個數代表第i個氣球總共被塗色的次數。

sample input

31 1

2 23 3

31 1

1 21 3

0sample output

1 1 1

3 2 1

區間修改查詢問題一般會想到用線段樹或者樹狀陣列來做,但是這題的特點就是多次修改,最後只有一次查詢,屬於離線查詢,即完成修改後再查詢,因此可以用到差分陣列.

#include

#include

#include

#include

#include

#include

using namespace std;

const

int maxn=

100010

;int d[maxn]

,sum[maxn]

;int

main()

for(

int i=

1;i<=n;i++

)for

(int i=

1;i)cout<

<<

" ";

cout<

<

}return0;

}

參考部落格 :

陣列定義的格式和方法的使用與定義

首先是陣列的建立格式,今天考試遇到了後幾種格式,以為是錯的,沒想到也可以,所以當時全部選錯了,希望各位能引以為戒。int arr new int 10 int arr int arr new int 以下幾種 int arr new int 4 int arr int arr new int int...

C語言 define巨集的定義與使用方法

一.巨集的概念與定義方法 1.被定義為 巨集 的標示符稱為 巨集名 在編譯預處理時,對程式中所有出現的 巨集名 都用巨集定義中德字串去替換,這稱為 巨集替換 或者 巨集展開 2.巨集定義是由源程式中德巨集定義命令完成的.巨集替換是由預處理程式自動完成的 在c語言中,巨集 分為有引數和無引數兩中.二....

陣列的定義與使用

宣告陣列 資料型別 陣列名稱 null 或者 資料型別 陣列名稱 null 開闢陣列 陣列名稱 new 資料型別 陣列長度 int data new int 100 陣列屬於引用資料型別,也需要進行記憶體分配,與物件儲存的唯一區別在於 物件中的堆記憶體儲存的是屬性,陣列中的堆記憶體儲存的是一組資訊。...