• 【ACM程序设计】差分


    差分

    假设有一个数列,我们需要对数列中的一个区间加上或减去一个值,直接想到的便是对该区间进行一次循环逐项加减。 但是当请求的操作变得非常多的时候,每次请求都进行一次循环会很容易爆时间,因此我们引入了差分算法.

    差分的特点就是在进行多次操作少量查询的时候可以快速得出结果。

    一维差分

    如果我们想将数列a[x,y]部分进行+num,只需要在 x 的差分数列b+numy+1的差分数列上-num 然后再对整个差分数列每一项求前缀和即得到结果也就是b[x] + num , b[y+1] - num

    空间优化

    由于我们修改区间一直在对差分数组进行操作,查询时对差分数组求前缀和

    因此我们可以在输入的时候就计算出差分数组,节省一个数组的空间

    int a[N], d[N];
    cin >> a[0];
    d[0] = a[0];
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        d[i] = a[i] - a[i-1];
    }

    二维差分

     

    二维差分即对一个矩形区间进行数据操作时使用

    由下图所示,如果已知原数组a,则可以求得差分数组p[x][y] = a[x][y] - a[x-1][\y] - a[x][y-1] + a[x-1][y-1]

    得出差分数组之后,我们想要对原数组中的亮蓝色区域进行数据操作,则需要在(x1,y1)对差分数组+1,但是这样子操作将会影响整个蓝色区域,因此我们需要在紫色橙色区域的对应位置进行-1 操作抵消影响,由于这俩块区域有一个交错范围因此需要在红色区域的对应位置进行 +1 操作。

    推导得在(x1,y1)(x2,y2)范围进行数据操作的公式为:

    d[x1][y1]+val; 
    d[x2+1][y1]-val;
    d[x1][y2+1]-val;
    d[x2+1][y2+1]+val;

    输入原数组并计算差分数组

    int a[N][N], d[N][N];
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cin >> a[i][j];
            d[i][j] = a[i][j] - a[i - 1][j] - a[i][j - 1] + a[i - 1][j - 1];
        }
    }

    区间修改

    void add(int i, int j, int x, int y, int val)
    {
        d[i][j] += val, d[x + 1][y + 1] += val;
        d[x + 1][j] -= val, d[i][y + 1] -= val;
    }

    第一节课——dfs、bfs、二分、尺取、前缀和、差分 - Virtual Judge (csgrandeur.cn)

    暴力解法:

    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    const int maxm = 1000;
    int m, n;
    int a[maxm][maxm] = {};
    int main()
    {
    cin >> m >> n;
    while (n--)
    {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    for (int i = x1; i <= x2; i++)
    {
    for (int j = y1; j <= y2; j++)
    {
    a[i][j]++;
    }
    }
    }
    for (int i = 1; i <= m; i++)
    {
    for (int j = 1; j <= m; j++)
    {
    cout << a[i][j] << ' ';
    }
    cout << endl;
    }
    return 0;
    }

    差分+前缀和

    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    const int maxm = 1000;
    int m, n;
    int d[maxm][maxm],sum[maxm][maxm];
    int main()
    {
    cin >> m >> n;
    while (n--)
    {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    d[x1][y1]++;
    d[x2 + 1][y2 + 1]++;
    d[x2 + 1][y1]--;
    d[x1][y2 + 1]--;
    }

    for (int i = 1; i <= m; i++)
    {
    for (int j = 1; j <= m; j++)
    {
    sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + d[i][j];
    cout << sum[i][j] << " ";
    }
    cout << endl;
    }
    return 0;
    }
     
  • 相关阅读:
    python学习之——pip的安装与使用
    python学习之——django环境搭建
    python学习之——eclipse+pydev 环境搭建
    linux学习之——vim简明教程
    深度公式
    带宽、延时、吞吐率、PPS
    人脸应用:人脸检测、人脸对比、五官检测、眨眼检测、活体检测、疲劳检测
    非交互式人脸活体检测(002)
    活体检测记录(001)
    Learning Generalizable and Identity-Discriminative Representations for Face Anti-Spoofing
  • 原文地址:https://www.cnblogs.com/tavee/p/16172344.html
Copyright © 2020-2023  润新知