差分(一维)(二维)

 一维差分

1.问题描述

输入一个长度为  的整数序列。

接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r]之间的每个数加上 c。

请你输出进行完所有操作后的序列。

输入格式

第一行包含两个整数 n和 m。

第二行包含 n个整数,表示整数序列。

接下来 m 行,每行包含三个整数 l,r,c,表示一个操作。

输出格式

共一行,包含 n 个整数,表示最终序列。

数据范围

1≤n,m≤100000
1≤l≤r≤n
−1000≤c≤1000
−1000≤整数序列中元素的值≤1000

2.算法分析

1.差分矩阵b[][],二维矩阵a[][],a数组中a[i][j]是b数组左上角(1,1)到右下角(i,j)所包围矩形元素的和。

2.如何构造b数组?逆向思考,a数组是b数组的前缀和,对一个小矩阵求和,其公式为:

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

3.构造差分数组:insert(i,j,i,j,a[i][j]);

3.代码实现

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int n,m;
    cin>>n>>m;
    vector<int> a(1,0);
    vector<int> s(1,0);
    //构造差分数组
    for(int i=1;i<=n;i++){
        cin>>a[i];
        s.push_back(a[i]-a[i-1]);
    }

    //操作差分数组
    while(m--){
        int l,r,c;
        cin>>l>>r>>c;
        s[l]+=c;
        s[r+1]-=c;
    }
    
    //输出
    int tmp=0;
    for(int i=1;i<=n;i++){
        tmp+=s[i];
        cout<<tmp<<" ";
    }
    
    return 0;
}

 二维差分

1.问题描述

输入一个 n 行 m 列的整数矩阵,再输入 q个操作,每个操作包含五个整数 x1,y1,x2,y2,c,其中 (x1,y1) 和 (x2,y2)表示一个子矩阵的左上角坐标和右下角坐标。

每个操作都要将选中的子矩阵中的每个元素的值加上 c。

请你将进行完所有操作后的矩阵输出。

输入格式

第一行包含整数 n,m,q。

接下来 n行,每行包含 m个整数,表示整数矩阵。

接下来 q行,每行包含 55 个整数 x1,y1,x2,y2,c,表示一个操作。

输出格式

共 n 行,每行 m个整数,表示所有操作进行完毕后的最终矩阵。

数据范围

1≤n,m≤1000
1≤q≤100000
1≤x1≤x2≤n
1≤y1≤y2≤m
−1000≤c≤1000
−1000≤矩阵内元素的值≤1000

2.算法分析

解决二维前缀和问题,需要将前缀和储存在二维数组中。

1.s[0][j]=0,s[i][0]=0,为初始条件,防止边界问题,

2.s[i][j]表示前i行j列的矩阵所有元素的和。s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j].

3.子矩阵的和为s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1].

3.代码实现 

#include<iostream>
using namespace std;
const int N=1010;

int a[N][N];//数组
int b[N][N];//差分矩阵

void insert(int x1,int y1,int x2,int y2,int c){
    b[x1][y1]+=c;
    b[x2+1][y1]-=c;
    b[x1][y2+1]-=c;
    b[x2+1][y2+1]+=c;
}

int main(){
    //输入
    int n,m,q;
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
        }
    }
    
    //初始化差分矩阵
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            insert(i,j,i,j,a[i][j]);
        }
    }
    
    //操作差分矩阵
    while(q--){
        int x1,y1,x2,y2,c;
        cin>>x1>>y1>>x2>>y2>>c;
        insert(x1,y1,x2,y2,c);
    }
    
    //由差分矩阵求改变后的矩阵(求二维前缀和)
        for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            b[i][j]+=b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
        }
    }
    
    //打印操作后的矩阵
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cout<<b[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值