前缀和&差分
本文最后更新于31 天前,其中的信息可能已经过时,如有错误请发送邮件到wsryhc@qq.com

前缀和

前缀和是为了方便计算在一个数组内的区间中的和,同时也包含二维数组计算。

一维前缀和

需要两个数组,一个是原数组,一个是记录前缀和的数组。
假设原数组为a,记录数组为b,那么b[0]=a[0];b[1]=b[0]+a[1];数组b中的第i个位置就是记录数组a中0~i的和。
加入需要求a[i]+…+a[j],只需要计算b[j]-b[i-1],就可以求出答案。

代码

int a[5]={1,2,3,4,5},b[5];
b[0]=a[0];
for(int i=1;i<5;i++){    //初始化数组b
    b[i]=b[i-1]+a[i];
}

二位前缀和

也是同时需要两个数组,一个为原数组,一个为记录前缀和数组。
注:计算时,在加上了[i-1][j]和[i][j-1]后,[i-1][j-1]项会被重复加一次,需要减掉。

代码

#include <iostream>
using namespace std;
const int N = 1010;
int n, m, q;
int 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", &s[i][j]);
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];    //注意需要减掉的元素
    while (q -- )
    {
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        printf("%d\n", s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]);
    }
    return 0;
}

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/39797/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

差分

若有一个数组,现在需要同时对他们一段区间全部进行加减一个数,差分算法只需要对于头尾进行修改,就可以修改区间全部数。

一维差分

还是同样需要一个原数组,一个记录差分的数组。
原数组a,记录数组b。a[0]==b[0];后面b[i]=a[i]-a[i-1]。在下一次需要进行输出的时候,只需要从b[0]开始每次加上下一个b数组就可以输出全部的数字,如果需要对于[i,j]区间全部加或者减一个数,只需要在b[i]加或者减那个数,然后在b[j+1]上补回来,这样就不需要全部进行操作。

代码

int a[5]={1,2,3,4,5};
int b[5];
b[0]=a[0];
for(int i=1;i<5;i++){
    b[i]=a[i]-a[i-1];
}
b[0]-=10;    //此处两行是对于第0~3位全部减去10的操作
b[3]+=10;
for(int i=0,j=0;i<5;i++){    //输出全部数组
    j+=b[i];
    printf("%d ",j);
}

二维差分

同样,只需要对于四个角的数字进行修改就可以修改区间矩阵的全部数字,需要进行反向的思维,一开始数组b为空的,每次输入就是插入在一个数字的范围加上输入的数,最后输出按照前缀和输出。

代码

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e3 + 10;
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, q;
    cin >> n >> m >> q;
    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 (q--)
    {
        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++)
        {
            b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];  //二维前缀和
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            printf("%d ", b[i][j]);
        }
        printf("\n");
    }
    return 0;
}

作者:林小鹿
链接:https://www.acwing.com/solution/content/27325/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如果有不正确内容,欢迎发至wsryhc@qq.com反馈,谢谢!
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇