前缀和:求l到r 的和
差分:求l到r 的都减去3的原数组
a的逐个差为b,b的前缀和为a
//1,求a3到ak,即Sk-S2
#include
using namespace std;
const int N=100010;
int a[N],s[N];
int main()
{
int n,m;
cin>>n>>m;
s[0]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];//s0+a1.s1+a2
}
while(m--)
{
int l,r;
cin>>l>>r;
cout<
称为预处理
叫区间修改
- 输入原数组。
- 差分。每两个数字的差值是差分的值
- 进行区间修改(本后加减)
- 求前缀和
- 再用前缀和打印原数组
6 2
413527
为6个数,进行两次加减再输入* * *几到几 加减几
- 注意在序号在线上,还是格子上
- 因为二次循环第一个循环是行。所以有的把(1.2)为第一行第二列,有的(1.2)为列
P5542 [USACO19FEB] Painting The Barn S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
教程:冯老师教信奥
二位差分:因为涂色的设为1,然后弄差分。若不设置为1那么用公式,即为差分的规律。
//解题二维
//这里的i.j都为行列号
#include
using namespace std;
const int MAXN(1e3);
//int a[MAXN+5][MAXN+5];
int b[MAXN+5][MAXN+5];
int main(){
int n,k;
cin>>n>>k;
while(n--){
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
b[x1+1][y1+1]++;//给的是坐标不是第几行。我们要化为行列数。
b[x1+1][y2+1]--;
b[x2+1][y1+1]--;
b[x2+1][y2+1]++;
}
int ans(0);
for(int i=1;i<=MAXN;i++){
for(int j=1;j<=MAXN;j++){
b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
if(b[i][j]==k){
ans++;
}
}
}
cout<
//using namespace std;
//const int MAXN(1e3);
//int a[MAXN+5][MAXN+5];
int b[MAXN+5][MAXN+5];
//
//int main(){
// int n,k;
// cin>>n>>k;
// while(n--){
// int x1,y1,x2,y2;
// cin>>x1>>y1>>x2>>y2;
// for(int i=x1+1;i<=x2;i++){
//给的是坐标不是第几行,行.i=x1+1或者是i<=x2-1前面不动。==============我们要化为行列数。
// for(int j=y1+1;j<=y2;j++){
// a[i][j]++;
// }
// }
// }
// int ans(0);
// for(int i=1;i<=MAXN;i++){
// for(int j=1;j<=MAXN;j++){
// if(a[i][j]==k){
// ans++;
// }
// }
// }
// cout<
注意:给的是坐标不是第几行,行.i=x1+1或者是i<=x2-1前面不动。==============我们要化为行列数。
为什么要差分:要求a【l到r】都加c:al+c......ar+c时间是O(n)
若差分就是O(1)
x1,y1到x2,y2的坐里面的求和
输入样例:
6 3 n,m
1 2 2 1 2 1 整数序列
1 3 1 m行个lrc
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2
//1acw一维差分
#include
#include
using namespace std;
const int N=100010;
int n,m;
int a[N],b[N];
void insert(int l,int r,int c)//不应该叫插入.应该区间修改得到b
{
b[l]+=c;
b[r+1]-=c;//因为insert(i,i,a[i])差分数组 b 的定义是:b[i] = a[i] - a[i-1],其中 a[0] = 0。
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);//数组
for(int i=1;i<=n;i++)insert(i,i,a[i]);//得到b
while(m--)//m行
{
int l,r,c;
scanf("%d%d%d", &l, &r, &c);
insert(l,r,c);//区间修改
}
for(int i=1;i<=n;i++)b[i]+=b[i-1];//b差分后自己弄前缀和
for(int i=1;i<=n;i++)printf("%d ",b[i]);
return 0;
}
本来要枚举所有元素,现在只要四个元素
初始化很简单,b全部设置为0,再把a插进去
输入
3 4 3 nmq
1 2 2 1 行m个整数
3 2 2 1
1 1 1 1
1 1 2 2 1 5个整数x1y1x2y2c
1 3 2 3 2
3 1 3 4 1
输出
2 3 4 1
4 3 4 1
2 2 2 2
//二维
#include
//#include
//#include
using namespace std;
const int N = 1010;
int a[N][N],b[N][N];
void change(int x1,int y1,int x2,int y2,int add)
{
b[x1][y1] += add;
b[x2+1][y1] -= add;
b[x1][y2+1] -= add;
b[x2+1][y2+1] += add;
}
int main()
{
int n,m,x;
cin >> n >> m >>x;
for (int i = 1; i <= n; i ++ )//n行
for (int j = 1; j <= m; j ++ ){//m列
scanf("%d", &a[i][j]);
change(i,j,i,j,a[i][j]);//a和把a加进去放在一个循环
}
int x1,x2,y1,y2,add;
for (int i = 0; i < x; i ++ ){//相当于一个while函数
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &add);
change(x1, y1, x2, y2, add);
}
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];//b差分后自己弄前缀和
cout << b[i][j] << ' ';
}
cout << endl;
}
return 0;
}