线性结构 —— 差分数组
生活随笔
收集整理的這篇文章主要介紹了
线性结构 —— 差分数组
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【差分數組】
差分數組不僅僅是一個優秀的線性結構,還是一種很好的思想,其主要用于修改區間、查詢單點,其中,修改區間的時間復雜度均為?O(1),查詢單點的時間復雜度為 O(n)
對于已知有 n 個元素的離線數列 a,可以建立一個記錄它每項與前一項差值的差分數組 f[],那么顯然有:
- f[1]=a[1]-0=a[1]
- f[i]=a[i]-a[i-1]
計算數列各項的值,可以發現:
- a[2]=f[1]+f[2]=a[1]+(a[2]-a[1])=a[2]
- a[3]=f[1]+f[2]+f[3]=a[1]+(a[2]-a[1])+(a[3]-a[2])=a[3]
- a[4]=f[1]+f[2]+f[3]+f[4]=a[1]+(a[2]-a[1])+(a[3]-a[2])+(a[4]-a[3])=a[4]
- ...
以此類推,可以發現數列 a 的第 i 項是可以用差分數組前 i 項和來計算的,即:a[i]=f[i] 的前綴和
計算數量每一項的前綴和,那么有:
即:可用差分數組來求出數列的前綴和
int a[N]; int f[N],sum[N]; void init(){f[1]=a[1];for(int i=2;i<=n;i++)//差分數組f[i]=a[i]-a[i-1];for(int i=1;i<=n;i++)//前綴和sum[i]=sum[i-1]+a[i]; }【差分數組用途】
1.快速處理區間加減
假如現在要對數列區間 [L,R] 上的每個數都加上 x,那么通過 a[i]=f[i] 的前綴和 的性質可以知道:
- 第一個受影響的差分數組中的元素為 f[L],所以令 f[L]+=x,那么后面數列元素在計算過程中都會加上 x
- 最后一個受影響的差分數組中的元素為 f[R],所以令 f[R+1]-=x,那么可以保證不會影響到 R 以后數列元素的計算
這樣一來,就不必對區間內每一個數進行處理,只需處理兩個差分后的數即可
void add(int L,int R,int x){f[L]+=x;f[R+1]-=x; } void sub(int L,int R,int x){f[L]-=x;f[R+1]+=x; }2.查詢單點
根據差分數組的性質,差分數組第?i 項的前綴和即為序列的第 i 項,因此可利用差分數組來計算原序列第?x 個點的值
int query(int x){int sum=0;for(int i=1;i<=x;i++)sum+=f[i];return sum; }【模版】
int n,m; int a[N]; int f[N],sum[N]; void init(){//求差分數組f[1]=a[1];for(int i=2;i<=n;i++)//差分數組f[i]=a[i]-a[i-1]; } void add(int L,int R,int x){//區間[L,R]全部加上xf[L]+=x;f[R+1]-=x; } void sub(int L,int R,int x){//區間[L,R]全部減去xf[L]-=x;f[R+1]+=x; } void query(int x){//查詢序列第i項int sum=0;for(int i=1;i<=x;i++)sum+=f[i];return sum; } int main(){cin>>n>>m;for(int i=1;i<=n;i++)//輸入序列cin>>a[i];init();//計算差分數組while(m--){//m個操作char op;cin>>op;if(op=='A'){//加操作int l,r,x;cin>>l>>r>>x;add(l,r,x);}else if(op=='S'){//減操作int l,r,x;cin>>l>>r>>x;sub(l,r,x);}else if(op=='Q'){//查詢操作int x;cin>>x;cout<<query(x)<<endl;}}return 0; }【例題】
總結
以上是生活随笔為你收集整理的线性结构 —— 差分数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信息学奥赛一本通——1000:入门测试题
- 下一篇: 序列中最大的数(51Nod-1062)