差分例题(一维--小明的彩灯&&二维--牛妹吃豆子)

​作者:小妮无语
专栏:暑假基础集训营

🚶‍♀️✌️道阻且长,不要放弃✌️🏃‍♀️

目录

例题一:小明的彩灯 (一维差分)

代码 

例题二:牛妹吃豆子(二维差分) 

代码 


例题一:小明的彩灯 (一维差分)

原题链接 

更详细的题解链接

注意数据范围 !!!

【样例输入】

5 3
2 2 2 1 5
1 3 3
4 5 5
1 1 -100

【样例输出】

0 5 5 6 10

代码 

#include <bits/stdc++.h>
using namespace std;
const int N=5*1e5+10;
int n,q;
//由于数据大小为1^9,数据量5*1^5,总的1^9*5*1^5=5*1^14,爆int
long long a[N],f[N];
int l,r,x;
int main()
{
  // 请在此输入您的代码
  cin>>n>>q;

  for(int i=1;i<=n;i++)
  {
    cin>>a[i];
    f[i]=a[i]-a[i-1];//当与将前缀和拆成原数组
  }
  while(q--)
  {
    cin>>l>>r>>x;
    f[l]+=x;
    f[r+1]-=x;
  }

  for(int i=1;i<=n;i++)
  {
    a[i]=a[i-1]+f[i];//把拆开的数组,使用前缀复原
    // if(a[i]<0) a[i]=0;
    //愚蠢了,这个特判不应该放里面,放里面,直接扰乱了前缀和的a[i-1]
    //如果本次a[i]<0,让a[i]直接为0,呢下一个要加它的本应加一个负数,但是加的为0
    // cout<<a[i]<<' ';
  }
  for(int i=1;i<=n;i++)
  {
    // a[i]=max(0,a[i]);出现了不匹配,由于a[i]为longlong类型,0为int造成数据类型不匹配的情况
    a[i]=max((long long)0,a[i]);//或者使用if判断
    cout<<a[i]<<' ';
  }
  return 0;
}

写错了两个地方

1.不因该把特判放到前缀和求和循环里写,扰乱了前缀和求和过程

2.将两个数据类型不同的数进行比较 

例题二:牛妹吃豆子(二维差分) 

原题链接

 

先说一下该题的注意点:

1.数据范围

2.开始时,棋盘是一个全0的二维数组,在上面局部区域放豆子,

就相当于,二维差分(x1,y1)左上角,(x2,y2)右下角

 3.对该棋盘进行复原,使用前缀和相加

4.把求和完的当作原数组,要求区域和,就使用二维前缀和,先进行叠加(对a[i][j]进行前缀和操作),再求区域和

 

代码 

#include<iostream>
using namespace std;
const int N=2010;
// int a[N][N],f[N][N];答案错误 用例通过率为 72.73%
//数据大小给的2^5,数据量2000*2000=4^6,4^6*2^5=8^11,爆int
long long a[N][N],f[N][N];
int n,m,k,q;
int x1,x2,y1,y2;
int main()
{
    cin>>n>>m>>k>>q;
    
    while(k--)
    {
        cin>>x1>>y1>>x2>>y2;
        a[x1][y1]+=1;
        a[x2+1][y1]-=1;
        a[x1][y2+1]-=1;
        a[x2+1][y2+1]+=1;//相当于对一个全为0的数组进行差分操作
    }
    
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            //把被拆开的数组使用前缀给复原,作为新的数组
            f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j];
            //再进行一次前缀和把新的数组进行累加
            //由于a[i][j]在下述不会再使用,所有直接进行覆盖,用来存前缀和
            a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+f[i][j];
        }

    }
    
    while(q--)
    {
        cin>>x1>>y1>>x2>>y2;
        //二维前缀和求区域和
        cout<<a[x2][y2]-a[x2][y1-1]-a[x1-1][y2]+a[x1-1][y1-1]<<endl;
    }
    return 0;
}

写错了两个点:

1.没注意数据范围,导致只过了 72.73%的样例

2.把求完差分后的原数组当作前缀和直接求起来区域和,导致本题全部出现错误,本意是先需要求差分,然后再完整的来一遍前缀和,本点要注意

 第二周例题over!!!

               == 欢迎来到暑假基础集训营的小菜鸟频道,睡不着就看看吧!==

跟着小张刷题吧!

                             ==  跟着小张刷题吧!==
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值