zoukankan      html  css  js  c++  java
  • 前缀与差分

    前缀与差分

    1. 算法分析

    1.1 前缀和

    定义
    s[n] = (sum_{i=1}^na[i])

    递推关系
    s[i] = a[i] + s[i - 1]

    区间求和
    (sum_{i=l}^ra[i] = s[r] - s[l - 1])

    1.2 差分

    定义
    存在两个数组a(a1, a2, a3,..., an)和b(b1, b2, ... ,bn)
    如果ai = b1 + b2 + ... + bi
    那么b称为a的差分(比如: b1 = a1, b2 = a2 - a1)

    作用

    1. 区间增加->单点修改:当a[l]~a[r]这个区间内元素全加上c时,只需要对b[l] + c, b[r+1] - c即可,因为:b[l] + c:让a[l]往后的元素全部加上c。b[r+1]-c:防止a[r+1]开始往后的元素加上c
    2. 一开始给ai赋值时,可以看成是给a[i]~a[i]这段全部加上c

    构造
    差分的构造可以选择: b[i] = a[i] - a[i - 1]

    变形
    差分可以维护a的变化值,即b[i] = Δai = $ sum_{i=1}^nb[i] $

    2. 板子

    2.1 前缀和

    2.1.1 一维前缀和

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int const N = 1e5 + 10;
    int s[N], a[N];
    
    int main()
    {
        int n, k;
        cin >> n >> k;
        // 计算前缀和
        for (int i = 1; i <= n ; ++i)
        {
            scanf("%d", &a[i]);
            s[i] = s[i - 1] + a[i];
        }
        
        // 使用前缀和
        for (int i = 0; i < k ; ++i)
        {
            int l, r;
            scanf("%d %d", &l, &r);
            printf("%d
    ", s[r] - s[l -1]);
        }
        return 0;
    }
    

    2.1.2 二维前缀和

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int const N = 1e3 + 10;
    int s[N][N], a[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)
            {
                scanf("%d", &a[i][j]);
                s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];  // 前缀和在二维的情况
            }
        for (int i = 0; i < k; ++i)
        {
            int l1, r1, l2, r2;
            scanf("%d %d %d %d", &l1 ,&r1, &l2, &r2);
            printf("%d
    ", s[l2][r2] - s[l2][r1 - 1] - s[l1 - 1][r2] + s[l1 - 1][r1 - 1]);  // 打印结果
        }
        return 0;
    }
    

    2.2 差分

    2.2.1 一维差分

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int const N = 1e5 + 10;
    int b[N], n, m, a[N];
    
    // 区间修改
    void insert(int l, int r, int c) {
        b[l] += c, b[r + 1] -= c;
    }
    
    int main() {
        cin >> n >> m;
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);  // 读入原数组
        for (int i = 1, l, r, c; i <= m; ++i) {  // 不断读入区间增加
            scanf("%d %d %d", &l, &r, &c);
            insert(l, r, c);  
        }
        for (int i = 1; i <= n; ++i) {
            b[i] += b[i - 1];  // 计算a[i]的变化值
            printf("%d ", a[i] + b[i]);
        }
        return 0;
    }
    

    2.2.1 二维差分

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int const N = 1e3 + 10;
    int a[N][N], b[N][N];
    int n, m, q;
    
    // 区间增加(二维情况)--和前缀和情况不一样
    void insert(int l1, int r1, int l2, int r2, int c)
    {
        b[l1][r1] += c;
        b[l2 + 1][r2 + 1] += c;
        b[l2 + 1][r1] -= c;
        b[l1][r2 + 1] -= c;
    }
    
    int main() {
        cin >> 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, l1, r1, l2, r2, c; i <= q; ++i) {
            scanf("%d%d%d%d%d", &l1, &r1, &l2, &r2, &c);  // 区间增加
            insert(l1, r1, l2, r2, 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];  // 前缀求和,计算变化量
                printf("%d ", a[i][j] + b[i][j]);  // 计算变化后的a[i][j]
            }
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    python模块—socket
    mac os系统的快捷键
    教你如何将UIImageView视图中的图片变成圆角
    关于ASP.NET MVC
    iOS 日期格式的转换
    将App通过XCode上传到AppStore 出现这个错误“An error occurred uploading to the iTunes Store”的解决方法
    关于MAC OS下面两个软件的功能改进——Dictionary和Fit 输入法
    分享一下上个星期的香港行程
    【博客园IT新闻】博客园IT新闻 iPhone 客户端发布
    解决Entity Framework Code First 的问题——Model compatibility cannot be checked because the database does not contain model metadata
  • 原文地址:https://www.cnblogs.com/spciay/p/13064104.html
Copyright © 2011-2022 走看看