字首和就是一直累加即可,可以用於非常極速\(O(1)\)的區間查詢。
差分則是取每兩個相鄰數字的差值,可以用於非常急速\(O(1)\)的區間修改,當然僅限加減。如果是乘除什麼的建議去線段樹
差分做一次字首和可以得到原陣列,原陣列再做一次字首和就是字首和......算了文字太繞了看下面的LaTeX吧:
\(差分\underset{差分}{\overset{字首和}{\rightleftharpoons}}原陣列\underset{差分}{\overset{字首和}{\rightleftharpoons}}字首和\)
#include<iostream>
using namespace std;
const int N = 100010;
int a[N];
int s[N];//字首和陣列
int d[N];//差分陣列
int main()
{
int n;
scanf("%d", &n);
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
s[i] += s[i-1] + t;//上一個總和加現在的數得到當前總和
d[i] = a[i] - a[i-1];//兩個數之間的差值就是差分陣列的目的
}
//對於查詢而言,直接將查詢區間頭和尾的值相減即可。
int l, r, v;
while(1)
{
int command;
scanf("%d%d%d%d", &command, &l, &r);/*假設1是字首和的操作,2是修改區間的操作
兩個修改的是兩組不同資料,只是為了演示作用*/
switch(command)
{
case 1:
cout<<d[r] - d[l-1]<<endl; //查詢從l到r的區間,因為包括了l,所以要往l-1位去找
break;
case 2:
scanf("%d", &v);
s[l]+=v;
s[r+1]-=v;//因為區間修改從l到r,包括r,因此要往後一項去減去一個v
//之所以要進行右端點減v,是因為修改的是一個區間,而差分修改一次會影響後面所有資料,所以在r+1的位置復原一次,保證後面區間不受影響。
break;
}
}
return 0;
}