🚶♀️✌️道阻且长,不要放弃✌️🏃♀️
目录
例题一:小明的彩灯 (一维差分)
注意数据范围 !!!
【样例输入】
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!!!
== 欢迎来到暑假基础集训营的小菜鸟频道,睡不着就看看吧!==
== 跟着小张刷题吧!==