1. 程式人生 > 其它 >序列演算法-字首和與差分

序列演算法-字首和與差分

技術標籤:ACM演算法

序列演算法-字首和

一般的字首和是對於陣列的求和,即對陣列的某一子陣列進行求和,即Sum(i,j) == sum[i] - sum[j-1]

不僅如此字首和還能用於任何含可逆運算的運算子包括異或xor

上述的子陣列和的問題屬於陣列固定,大量訪問的問題優化。

下面給出一個大量做區間加的情況:

給定一個序列a 有很多次操作,每個操作形如:A l r k 將a_[l,r]每個值加上k. 最後輸出整個陣列。複雜度要求O(n).

如果用傳統方法,n次操作當lr區間長度達到n就成了O(n^2)了,自然不符合題意。

所以這裡利用到了差分陣列(描述序列元素的遞推關係,以更快的方式體現序列元素的增減)。

對於如下序列:

5 4 7 2 4 3 1

經過如下計算:

得到差分陣列:

5 -1 3 -5 2 -1 -2

然後再求差分陣列的字首和可以發現:

sum[i] == line[i]

並且給差分陣列的一個元素+x後,其後面直到-x的元素(不包括),他們的字首和均+i(即line元素+i),這就回歸到了我們的題目要求上。

由查分陣列的這些性質可以解決更多類似這種問題。

所以程式碼如下:

int n;//陣列元素個數
int l,r,k;
int a[100005];
int change[100005];
int sum[100005];

void fun(int m)//m次操作
{
    memset(change,
0,sizeof(change)); memset(sum,0,sizeof(sum)); for(int i = 1;i <= n;i++) //求差 { cin >> a[i]; change[i] += a[i] - a[i-1]; } for(int i = 0;i < m;i++) //對差分元素進行加減運算 { cin>>l>>r>>k; change[l] += k; change[
r + 1] -= k; } for(int i = 1;i <= n;i++) //求差分陣列字首和並輸出 { sum[i] = sum[i-1] + change[i]; cout<<sum[i]<<" "; } }