序列演算法-字首和與差分
阿新 • • 發佈:2021-02-17
序列演算法-字首和
一般的字首和是對於陣列的求和,即對陣列的某一子陣列進行求和,即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]<<" ";
}
}