淺談差分數組的原理及簡單應用

##1、差分數組的定義及用途 ###1.定義: 對於已知有n個元素的離線數列d,咱們能夠創建記錄它每項與前一項差值的差分數組f:顯然,f[1]=d[1]-0=d[1];對於整數i∈[2,n],咱們讓f[i]=d[i]-d[i-1]。 ###2.簡單性質: (1)計算數列各項的值:觀察d[2]=f[1]+f[2]=d[1]+d[2]-d[1]=d[2]可知,數列第i項的值是能夠用差分數組的前i項的和計算的,即d[i]=f[i]的前綴和。 (2)計算數列每一項的前綴和:第i項的前綴和即爲數列前i項的和,那麼推導可知 便可用差分數組求出數列前綴和; ###3.用途: ####(1)快速處理區間加減操做: 假如如今對數列中區間[L,R]上的數加上x,咱們經過性質(1)知道,第一個受影響的差分數組中的元素爲f[L],即令f[L]+=x,那麼後面數列元素在計算過程當中都會加上x;最後一個受影響的差分數組中的元素爲f[R],因此令f[R+1]-=x,便可保證不會影響到R之後數列元素的計算。這樣咱們沒必要對區間內每個數進行處理,只需處理兩個差分後的數便可; ####(2)詢問區間和問題: 由性質(2)咱們能夠計算出數列各項的前綴和數組sum各項的值;那麼顯然,區間[L,R]的和即爲ans=sum[R]-sum[L-1]; ##2、相關題目 ###1.[HDU1556]Color the ball ####Descriptionhtml

-N個氣球排成一排,從左到右依次編號爲1,2,3....N.每次給定2個整數a b(a <= b),lele便爲騎上他的「小飛鴿"牌電動車從氣球a開始到氣球b依次給每一個氣球塗一次顏色。可是N次之後lele已經忘記了第I個氣球已經塗過幾回顏色了,你能幫他算出每一個氣球被塗過幾回顏色嗎? -Input:每一個測試實例第一行爲一個整數N,(N <= 100000).接下來的N行,每行包括2個整數a b(1 <= a <= b <= N)。當N = 0,輸入結束。 -Output:每一個測試實例輸出一行,包括N個整數,第I個數表明第I個氣球總共被塗色的次數。 ####Solution 1.記錄各次操做,對差分數組進行對應修改,改變量爲1(用途1); 2.使用性質(1)計算各項的值便可;ios

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std; 
int d[100010],a[100010],l,r;
int main(){
	int n;
	while(scanf("%d",&n),n)
	{
		memset(d,0,sizeof(d));
		memset(a,0,sizeof(a));
		for(int i=1;i<=n;++i){
			scanf("%d%d",&l,&r);
			d[l]+=1;
			d[r+1]-=1;
		}
		for(int i=1;i<=n;++i) a[i]=a[i-1]+d[i];
		for(int i=1;i<n;++i) printf("%d ",a[i]);
		printf("%d\n",a[n]);
	}
	return 0;
}

###2.[NKOJ3754]數列遊戲 ####Description數組

-給定一個長度爲N的序列,首先進行A次操做,每次操做在Li和Ri這個區間加上一個數Ci。 而後有B次詢問,每次詢問Li到Ri的區間和。 初始序列都爲0。 -輸入格式: 第一行三個整數N A B。(1<=N<=1000000,1<=A<=N,A<=B<=N) 接下來A行,每行三個數Li Ri Ci。(1<=Li<=N,Li<=Ri<=N,|Ci|<=100000000000000)。 接下來B行,每行兩個數 Li Ri。範圍同上。 -輸出格式: 對於每次詢問,輸出一行一個整數。 由於最後的結果可能很大,請對結果mod 1000000007。 ####Solution 1.應用(1)處理區間加; 2.用性質(1)求出修改後數列,再求出相應數列和(應用2)或直接用性質(2)求解; 3.注意隨時取模;數據結構

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
const long long mod=1000000007; 
using namespace std;
long long d[100010],f[100010],sum[100010];
int main(){
	int n,a,b;
	scanf("%d%d%d",&n,&a,&b);
	memset(d,0,sizeof(d));
	memset(f,0,sizeof(f));
	memset(sum,0,sizeof(sum));
	for(int i=1;i<=a;++i){
		long long l,r,c;
		scanf("%ld%ld%ld",&l,&r,&c);
		f[l]=(f[l]+c)%mod;
		f[r+1]=(f[r+1]-c)%mod;
	}
	for(int i=1;i<=n;++i)  d[i]=(d[i-1]+f[i])%mod;
	for(int i=1;i<=n;i++) sum[i]=(sum[i-1]+d[i])%mod;
	for(int i=1;i<=b;++i){
		int l,r;
		scanf("%d%d",&l,&r);
        printf("%ld\n",(sum[r]-sum[l-1])%mod);
		//printf("%ld\n",temp>=0?temp:temp+mod);//防止結果爲負; 
	}
	return 0;
}

###3.[NOIP2012提升&洛谷P1083]借教室 ###題解隨筆:http://www.cnblogs.com/COLIN-LIGHTNING/p/8467795.html ###4.[洛谷P3948]數據結構 ###題解隨筆:http://www.cnblogs.com/COLIN-LIGHTNING/p/8482463.html測試

相關文章
相關標籤/搜索