前缀和&差分

前缀和子矩阵:

#include <iostream>
using namespace std;
const int N = 1010;
int a[N][N],s[N][N];
int main()
{
    int n,m,k;
    cin>>n>>m>>k;
    for(int i = 1;i<=n;i++)
        for(int j = 1;j<=m;j++)
        {
            cin>>a[i][j];
            s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
        }
    while(k--)
    {
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        int t = s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1];
        cout<<t<<endl;
    }

    return 0;
}
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
差分:
#include <iostream>
using namespace std;
const int N = 100010;
int a[N],b[N];
void insert(int l, int r, int c)
{
    b[l] += c;
    b[r+1] -= c;
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i = 1;i<=n;i++)
        cin>>a[i];
    for(int i = 1;i<=n;i++) insert(i, i, a[i]);
    while(m--)
    {
        int l,r,c;
        cin>>l>>r>>c;
        insert(l, r, c);
    }
    for (int i = 1; i<=n; i++)
        a[i] = a[i-1] + b[i];
    for(int i = 1;i<n;i++)
        cout<<a[i]<<" ";
    cout<<a[n]<<endl;
    
    return 0;
}

构造差分数组:a[i] = b[1] + b[2] + ... + b[i];

那么如何通过已知的a数组来得出b数组呢?通过insert(i,i,a[i]); b[l] += c; b[r+1] -= c;

可以模拟一下,比如

b[1] = b[1] + a[1] = a[1]; b[2] = -a[1];

b[2] = b[2] + a[2] = -a[1] + a[2];---> a[2] = a[1] + b[2] = b[1] + b[2] ; b[3] = -a[2];

b[3] = -a[2] + a[3]; ---> a[3] = a[2] + b[3] = b[1] + b[2] + b[3] ;b[4] = -a[3];

非常巧妙。

由a数组得到差分数组b之后,就可以通过前缀和,a[n] = a[n-1] + b[n];来输出a[n]即可。

猜你喜欢

转载自www.cnblogs.com/longxue1991/p/12650773.html