[学习笔记]二维前缀和+差分

不问归期 提交于 2019-12-02 10:24:28

[学习笔记]二维前缀和+差分

题面

导入

先来了解一下差分。
有一个$1~n$的序列,请将它的前$m$($m < n$)项$+1$,并求出前$n$项的前缀和。
你可以新建一个数组并清零,在第一项加上一个$1$,并在第$m+1$项填上一个$-1$。
设$n = 6,m = 4$
|原序列|1|2|3|5|7|4|
|-|-|-|-|-|-|
|新数组|1|0|0|0|-1|0|
接着,求一遍新数组的前缀和:
|新数组|1|1|1|1|0|0|
|-|-|-|-|-|-|

然后把新数组的前缀和加到原序列中
|最终数组|2|3|4|6|7|4|
|-|-|-|-|-|-|

所以就求出来了

二维前缀和+差分

读题可知,输入$x1,y1,x2,y2$
需要将这个矩阵中的所有的数$+1$
二维其实和一维差不多,只是把一个一维序列倒过来:
|1|
|-|
|2|
|3|
|5|
|7|
|4|
所以只需要把矩阵左上角$+1$,右上角的后一个$-1$,右下角$+1$,左下角的下一个元素$-1$
接着统计前缀和的时候,$mapp[i][j] = mapp[i][j] + mapp[i][j - 1] + mapp[i - 1][j] - mapp[i - 1][j - 1]$

code

#include <bits/stdc++.h>
using namespace std;
int mapp[5010][5010];
void read(int &x){
    x = 0;
    bool flag = true;
    char ch = getchar();
    while(!isdigit(ch)){
        if(ch == '-')
            flag = false;
        ch = getchar();
    }
    while(isdigit(ch)){
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    if(!flag)
        x = -x;
}
int main(){
    int n,m,q;
    read(n);
    read(m);
    read(q);
    for(int i = 1;i <= q;i++){
        int x1,y1,x2,y2;
        read(x1);
        read(y1);
        read(x2);
        read(y2);
        mapp[x1][y1]++;
        mapp[x2 + 1][y2 + 1]++;
        mapp[x1][y2 + 1]--;
        mapp[x2 + 1][y1]--;
    }
    for(int i = 1;i <= n + 1;i++){
        for(int j = 1;j <= m + 1;j++){
            mapp[i][j] += mapp[i][j - 1] + mapp[i - 1][j] - mapp[i - 1][j - 1];
        }
    }
    long long ans = 0;
    for(register long long i = 1;i <= n;i++){
        for(register long long j = 1;j <= m;j++){
            if(mapp[i][j] == 0)continue;
            ans += 2;
            if(mapp[i][j] > mapp[i][j - 1])
                ans += (long long)mapp[i][j] - mapp[i][j - 1];
            if(mapp[i][j] > mapp[i - 1][j])
                ans += (long long)mapp[i][j] - mapp[i - 1][j];
            if(mapp[i][j] > mapp[i + 1][j])
                ans += (long long)mapp[i][j] - mapp[i + 1][j];
            if(mapp[i][j] > mapp[i][j + 1])
                ans += (long long)mapp[i][j] - mapp[i][j + 1];
        }
    }
    printf("%lld\n",ans);
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!