AcWing算法基础课-基础算法-前缀和与差分

目录

1、一维前缀和

1.1 模板

1.2 例题

2、二维前缀和

2.1 模板

2.2 例题

3、一维差分

3.1 模板

3.2 例题

4、二维差分

4.1 模板

4.2 例题

1、一维前缀和

1.1 模板

S[i] = a[1] + a[2] + ... a[i]
a[l] + ... + a[r] = S[r] - S[l - 1]

1.2 例题

题目来源:AcWing
题目链接:AcWing 795. 前缀和
代码展示:

#include <iostream>

using namespace std;

const int N = 1e6 + 10;

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

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    for(int i = 1; i <= n; i ++) S[i] = S[i - 1] + a[i];
    
    while(m --){
        int l, r;
        scanf("%d%d", &l, &r);
        cout << S[r] - S[l - 1] << endl;
    } 
    
    return 0;
}

2、二维前缀和

2.1 模板

//S[i, j] = 第i行j列格子左上部分所有元素的和
//以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]

2.2 例题

题目来源:AcWing
题目链接:AcWing 796. 子矩阵的和
代码展示:

#include <iostream>

using namespace std;

const int N = 1e3 + 10;

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

int main()
{
    scanf("%d%d%d", &n, &m, &q);
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
            scanf("%d", &a[i][j]);
            
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
            s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j];
    while(q --){
        int x1, y1, x2, y2, tmp;
        cin >> x1 >> y1 >> x2 >> y2;
        tmp = s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1];
        cout << tmp << endl;
    }
    
    return 0;
}

3、一维差分

3.1 模板

//给区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c

3.2 例题

题目来源:AcWing
题目链接:AcWing 797. 差分
代码展示:

#include <iostream>

using namespace std;

const int N = 1e6 + 10;

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

void insert(int l, int r, int c){
    b[l] += c;
    b[r + 1] -= c;
}

int main()
{
    scanf("%d%d", &n,&m);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    for(int i = 1; i <= n; i ++) insert(i, i, a[i]);
    
    while(m --){
        int l, r, c;
        cin >> l >> r >> c;
        
        b[l] += c;
        b[r + 1] -= 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] << " ";
    
    return 0;
}

4、二维差分

4.1 模板

//给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c

4.2 例题

题目来源:AcWing
题目链接:AcWing 798. 差分矩阵
代码展示:

#include <iostream>

using namespace std;

const int N = 1e3 + 10;

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

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

int main()
{
    scanf("%d%d%d", &n, &m, &q);
    
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
            scanf("%d", &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;
        scanf("%d%d%d%d%d", &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 ++)
            a[i][j] = a[i][j - 1] + a[i - 1][j] - a[i - 1][j - 1] + b[i][j];
    
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++){
            cout << a[i][j] << " ";
            if(j == m) cout << endl;
        }
        
    return 0;
}

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值