字首和與差分

ComputerEngine發表於2024-03-21

​ 字首和就是一直累加即可,可以用於非常極速\(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;
}

相關文章