差分
输入一个长度为 n 的整数序列。
接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c。
请你输出进行完所有操作后的序列。
输入格式
第一行包含两个整数 n 和 m。
第二行包含 n 个整数,表示整数序列。
接下来 m 行,每行包含三个整数 l,r,c,表示一个操作。
输出格式
共一行,包含 n 个整数,表示最终序
数据范围
1≤n,m≤100000
1≤l≤r≤n,
−1000≤c≤1000
−1000≤整数序列中元素的值≤1000
输入样例:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
b[i]=a[i]-a[i-1]; //构建差分数组
}
//上面是构建差分数组,
// b[1]=a[1]-a[0]
// b[2]=a[2]-a[1]
// b[3]=a[3]-a[2]
// ·········
// b[6]=a[6]-a[5];
//目的是为了在前缀和中通过b里的某个元素修改后去修改a后面的值
//构造了差分数组后就已经有了比如a[3]=b[3]+b[2]+b[1];这种前缀和关系。
//只不过现在不用,因为为了去修改a的值我们还需要对中间的b进行修改,所以接下来
//是先对b修改,再调用a[3]=b[3]+b[2]+b[1];
int l,r,c;
while (m--)
{
scanf("%d%d%d", &l, &r, &c);
b[l] += c; //将序列中[l, r]之间的每个数都加上c
b[r + 1] -= c;
}
//调用a[3]=b[3]+b[2]+b[1];这种前缀和运算。
for (int i = 1; i <= n; i++)
{
a[i] = b[i] + a[i - 1]; //前缀和运算
printf("%d ", a[i]);
}
//前缀和运算a[3]=b[3]+b[2]+b[1] 因为前面已经构造了差分数组所以此时一定是成立的 //而且如果 中间的某个b不变的话那么a 就不会变。
// a[3]=b[3]+b[2]+b[1]
//a[4]=b[4]+b[3]+b[2]+b[1]
//他们可以直接写成这个样子
//那么对中间的b[3] 修改了就是对a[3] 之后的值都修改了
//这种。
return 0;
}
另外的代码:
#include<iostream>
using namespace std;
const int N=100010;
int a[N],b[N];
void insert(int l,int r,int c)
{ //a[0]=0;
b[l]+=c; //定义b[1]=a[1]-a[0];
b[r+1]-=c; //b[2]=a[2]-a[1];b[3]=a[3]-a[2];
} // a[3]=b[1]+b[2]+b[3];
int main() //所以在[l,r]之间加上c,相当于在b[l]+c;那么[a[l],a[n]]都加上了c
{ //因为要在r之前,所以在b[r+1]-c; 那么[a[r+1],a[n]]都减去了c;
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i]; //相当于在[i,i]之间加上a[i]
insert(i,i,a[i]);//将a[i]以加的方式插入b[i]当中
}
while(m--)
{
int l,r,c;
cin>>l>>r>>c;
insert(l,r,c);//在[l,r]之间加上c
}
for(int i=1;i<=n;i++) b[i]+=b[i-1];// 相当于b[1]=b[1]+b[0]=a[1]
for(int i=1;i<=n;i++) cout<<b[i]<<" ";// b[2]=b[2]+b[1]=a[2]-a[1]+a[1]=a[2];
return 0;
}
差分矩阵
输入一个 n 行 m 列的整数矩阵,再输入 q 个操作,每个操作包含五个整数 x1,y1,x2,y2,c其中 (x1,y1) 和 (x2,y2) 表示一个子矩阵的左上角坐标和右下角坐标。
每个操作都要将选中的子矩阵中的每个元素的值加上 c。
请你将进行完所有操作后的矩阵输出。
输入格式
第一行包含整数 n,m,q。
接下来 n 行,每行包含 m 个整数,表示整数矩阵。
接下来 q 行,每行包含 5 个整数 x1,y1,x2,y2,c,表示一个操作。
输出格式
共 n 行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。
数据范围
1≤n,m≤1000,
1≤q≤100000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
−1000≤c≤1000,
−1000≤矩阵内元素的值≤1000
输入样例:
3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1
输出样例:
2 3 4 1
4 3 4 1
2 2 2 2
代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1010;
int n,m,q,c;
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()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);//先输入a[i][j]
insert(i,j,i,j,a[i][j]);//在(i,j)到(i,j)的位置加上a[i][j]
}
while(q--)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
insert(x1,y1,x2,y2,c);//在(x1,y1)到(x2,y2)的位置加上c
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+b[i][j];//前缀和的形式
cout<<a[i][j]<<" ";
}
puts("");
}
return 0;
}
b[x1][ y1 ] +=c ; 对应图1 ,让整个a数组中蓝色矩形面积的元素都加上了c。
b[x1,][y2+1]-=c ; 对应图2 ,让整个a数组中绿色矩形面积的元素再减去c,使其内元素不发生改变。
b[x2+1][y1]- =c ; 对应图3 ,让整个a数组中紫色矩形面积的元素再减去c,使其内元素不发生改变。
b[x2+1][y2+1]+=c; 对应图4,,让整个a数组中红色矩形面积的元素再加上c,红色内的相当于被减了两次,再加上一次c,才能使其恢复。