• 前缀和&差分


    前缀和子矩阵:

    #include <iostream>
    using namespace std;
    const int N = 1010;
    int a[N][N],s[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++)
            {
                cin>>a[i][j];
                s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
            }
        while(k--)
        {
            int x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            int t = s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1];
            cout<<t<<endl;
        }
    
        return 0;
    }
    s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
    差分:
    #include <iostream>
    using namespace std;
    const int N = 100010;
    int a[N],b[N];
    void insert(int l, int r, int c)
    {
        b[l] += c;
        b[r+1] -= c;
    }
    int main()
    {
        int n,m;
        cin>>n>>m;
        for(int i = 1;i<=n;i++)
            cin>>a[i];
        for(int i = 1;i<=n;i++) insert(i, i, a[i]);
        while(m--)
        {
            int l,r,c;
            cin>>l>>r>>c;
            insert(l, r, 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]<<" ";
        cout<<a[n]<<endl;
        
        return 0;
    }

    构造差分数组:a[i] = b[1] + b[2] + ... + b[i];

    那么如何通过已知的a数组来得出b数组呢?通过insert(i,i,a[i]); b[l] += c; b[r+1] -= c;

    可以模拟一下,比如

    b[1] = b[1] + a[1] = a[1]; b[2] = -a[1];

    b[2] = b[2] + a[2] = -a[1] + a[2];---> a[2] = a[1] + b[2] = b[1] + b[2] ; b[3] = -a[2];

    b[3] = -a[2] + a[3]; ---> a[3] = a[2] + b[3] = b[1] + b[2] + b[3] ;b[4] = -a[3];

    非常巧妙。

    由a数组得到差分数组b之后,就可以通过前缀和,a[n] = a[n-1] + b[n];来输出a[n]即可。

    同理二维差分矩阵,可以类似于从一维差分和前缀和子矩阵两种结合起来得到:

    #include <iostream>
    using namespace std;
    const int N = 1010;
    int a[N][N],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,k;
        cin>>n>>m>>k;
        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(k--)
        {
            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++)
                a[i][j] = a[i-1][j]+a[i][j-1] - 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]<<" ";
            cout<<endl;
        }
        
        return 0;
    }

     同样可以模拟一下:

    b[1][1] = a[1][1];b[1][2] = -a[1][1] = -b[1][1], b[2][1] = -b[1][1];b[2][2] = a[1][1] = b[1][1];

    b[1][2] = -b[1][1] + a[1][2], --->a[1][2] = b[1][1] + b[1][2], b[2][2] = -a[1][2]...

    b[2][1] = -b[1][1] + a[2][1],--->a[2][1] = b[1][1] + b[2][1], b[2][2] = -a[2][1]...

    b[2][2] = -a[1][2] - a[2][1] + b[1][1] + a[2][2],--->a[2][2] = a[1][2] + a[2][1] - b[1][1] = b[1][1] + b[1][2] + b[1][1] + b[2][1] - b[1][1] + b[2][2] = b[1][1] + b[1][2] + b[2][1] + b[2][2];

    可以看到这样就可以得到a数组是b数组的前缀二维子矩阵和了。

     
  • 相关阅读:
    协方差与协方差矩阵
    boost.python笔记
    2014年8月3日
    工作记录
    工作记录
    工作记录
    sed教程
    Visual studio C++ 之空控制台工程添加文件并解决头文件包含问题
    Visual studio C++ MFC之列表控件CListCtrl Control
    Visual studio C++ MFC之点击按钮(菜单栏)生成新窗口
  • 原文地址:https://www.cnblogs.com/longxue1991/p/12650773.html
Copyright © 2020-2023  润新知