第三期前缀和与差分(一维和二维)

一. 我的思想

这两个算法十分重要,需要牢牢记住,然后灵活使用!


二.一维前缀和

核心代代码:

1.初始化的时候:

   p[i] = p[i - 1] + a[i];

2.计算的时候,其实和等差数列差不多啦:

ans=p[r] - p[l - 1];

上题目:

蓝精灵

上代码:

#include<bits/stdc++.h>
using namespace std;
int a[100006],p[100006]={0};
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <=n;i++)
        {
            cin >>a[i];
            p[i] = p[i - 1] + a[i];//核心部分
        }
    while(m--)
    {
        int l, r;
        cin >> l >> r;
        if(l>r)
        {
          swap(l,r);
        }
        int ans=p[r] - p[l - 1];//核心部分
        cout<<ans<<endl;
    }
    }

这个还是非常简单的。


三.一维差分

注意要先全修改完,再相加

核心代码

void insert(int l,int r,int c)
{
    b[l] += c;
    b[r + 1] -= c;
}

就是与前一项的差值,l到r的部分都加上一个常数,然后加起来就可以得到答案啦。

上代码

#include<bits/stdc++.h>
using namespace std;
int a[100005], b[100005];
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];
    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++)
   {
       b[i] += b[i - 1];//当前的数组与前一项的差值加上前一数组的值就是答案
       cout << b[i] << ' ';
   }
}

四.二维前缀和

我一般画图理解。

核心代码部分:

1.初始化:

sum[i][j] = a[i][j] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];

2.计算结果:
sum[x3][y3] - sum[x3][y2 - 1] - sum[x2 - 1][y3] + sum[x2 - 1][y2 - 1]

上题目:

二维前缀

上代码:

#include<bits/stdc++.h>
using namespace std;
int a[10005][10005];
int sum[10005][10005];
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];
            sum[i][j] = a[i][j] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
    }
    }
    while(q--)
    {
        int x2, x3, y2, y3;
        cin >> x2 >> y2 >> x3 >> y3;
        cout << sum[x3][y3] - sum[x3][y2 - 1] - sum[x2 - 1][y3] + sum[x2 - 1][y2 - 1]<<endl;
    }
}

二维差分

也是画图理解,就容易记了。

核心代码

初始化:

void insert(int x1,int y1,int x2,int y2,int c)
{
    b[x1][y1] += c;
    b[x1][y2 + 1] -= c;
    b[x2 + 1][y1] -= c;
    b[x2+1][y2+1]+=c;
}

计算每一项的值:

 b[i][j] = b[i][j] + b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];

上题目:

二维差分

代码!:

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int a[N][N], b[N][N];
void insert(int x1,int y1,int x2,int y2,int c)
{
    b[x1][y1] += c;
    b[x1][y2 + 1] -= c;
    b[x2 + 1][y1] -= 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];
            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][j] + b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
            cout << b[i][j] << ' ';
        }
        cout << endl;
    }
}

#六.总结
这个要好理解我认为要画图动脑理解,这两个算法很容易和别的一起出我这有个以前写的他和二分一起出的题:换教室:二分+差分
就是这个。加油多刷题!!!
kon!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值