差分

差分:
当频繁的对数组内的元素进行区域性性的加减运算的时候使用差分
差分数组的第一个值等于源数组的第一个值
差分数组的第k个值等于原数组第k个值减去第k-1个值
当要让原数组的 [L,R]区域内每个元素都 加/减 c的时候
只需要差分数组的[L](+/ -)c,差分数组的[R+1](-/+)c
最后原数组的结果等于差分数组的前缀和数组

题目:

输入样例:

6 3 
1 2 2 1 2 1 
1 3 1 
3 5 1 
1 6 1

期望输出:

3 4 5 3 4 2 

代码实现:

#include<bits/stdc++.h>
using namespace std;

const int N =1e6+10;

int n,m;
int a[N],b[N];

int main()
{
    cin>>n>>m;

    //输入a数组元素并且预处理差分数组b
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        b[i]= a[i] - a[i-1];
    }

    while(m--)
    {
        int l ,r,k;
        cin>>l>>r>>k;
        b[l]+=k;
        b[r+1]-=k;
    }

    int t = 0;
    //对b数组求前缀和即可得到最终数列
    for(int i=1;i<=n;i++)
    {
        t=t+b[i];
        printf("%d ",t);
    }

}

------------------------------------------------------------------------------------------------------------------------------------

二维差分

二维差分数组b[i,j]要使原数组a[i,j]是右上角所有b[i,j]元素的前缀和

要使的某个区间同时加上一个数c,只需要把 b[x1,y1] +c , b[x1,y2 +1] +c , b[x2 +1,y1] -c , b[x2 +1,y2 +1] +c 

题目:

输入样例:

3 4 3 
1 2 2 1 
3 2 2 1 
1 1 1 1 
1 1 2 2 1 
1 3 2 3 2 
3 1 3 4 1 

期望输出:

2 3 4 1 
4 3 4 1 
2 2 2 2

代码实现:

#include<bits/stdc++.h>
using namespace std;

const int N = 1010;

int n,m,q;
int a[N][N],b[N][N];

int main()
{
    cin>>n>>m>>q;
    //输入a数组并且预处理得到差分数组b
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            b[i][j]=a[i][j] -a[i-1][j] -a[i][j-1] +a[i-1][j-1];
        }
    }

    int x1,y1,x2,y2,c;

    //对差分数组进行操作
    while(q--)
    {
        cin>>x1>>y1>>x2>>y2>>c;

        b[x1][y1]+=c;
        b[x1][y2+1]-=c;
        b[x2+1][y1]-=c;
        b[x2+1][y2+1]+=c;
    }

    //此时b仍然是差分数组,是处理完成后的差分数组,对b求前缀和,得到结果数组
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+b[i][j];
            printf("%d ",a[i][j]);
        }
        puts("");
    }
}
posted @ 2023-04-07 15:36  小花护符  阅读(27)  评论(0)    收藏  举报