一维前缀和
代码实现:
- 计算公式:S[r]-S[l-1]=l~r范围和
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <stdio.h>
using namespace std;
const int N=100010;
int n, m; //n表示数组已存入的数个数,m表示需要查询的次数
int A[N], S[N];
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++)S[i] = S[i - 1] + A[i];
while (m--)
{
int l, r;
scanf("%d%d", &l, &r); //区间和的计算
printf("%d\n",S[r] - S[l - 1]);
}
system("pause");
return 0;
}
一维前缀和(2)
//计算一维前缀和(q次询问,输入l和r,输出l->r之间的和值)
//公式:sum[l->r]=sum[r]-sum[l-1];sum[i]=a[i]+sum[i-1];
void test01()
{
int a[1000] = { 0 }, sum[1000] = { 0 }; sum[0] = 0;
int n, q, l, r;
cin >> n >> q;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
}
while (q--) {
cin >> l >> r;
printf("%d", sum[r] - sum[l - 1]);
}
}
二维前缀和
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
const int N = 1010;
int n, m, q;
int a[N][N], s[N][N];
int main()
{
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &a[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j]; //求前缀和
while (q--)
{
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
printf("%d\n", s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]); //求子矩阵
}
return 0;
}
二维前缀和(2)
//计算二维前缀和
//前缀和数组公式:sum[x][y] = sum[x - 1][y] + sum[x][y - 1] - sum[x - 1][y - 1] + a[x][y];
//子矩阵 :sum[x_2-x_1][y_2-y_1]=sum[x_2][y_2]-sum[x_2][y_1-1]-sum[x_1-1][y_2]+sum[x_1-1][y_1-1];
//例题:求区间[x_1,y_1]->[x_2,y_2]区间中数值之和
void test03()
{
int a[50][50] = { 0 }, sum[50][50] = { 0 };
int n, m, q; //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] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
}
while (q--)
{
int x_1, y_1, x_2, y_2;
cin >> x_1 >> y_1 >> x_2 >> y_2;
cout << sum[x_2][y_2] - sum[x_1 - 1][y_2] - sum[x_2][y_1 - 1] + sum[x_1 - 1][y_1 - 1] << endl;
}
}
一维差分
- 原理:有一数列{a1,a2,a3…an}构造{b1,b2,b3…bn}使得an=b1+b2+…+bn.
- 代码实现:
给区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c
#include <iostream>
using namespace std;
const int N = 10010;
int n, m;
int a[N], b[N];
void insert(int l, int r, int c)
{
b[l] += c;
b[r + 1] -= c;
}
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]);
while (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];
for (int i = 1; i <= n; i++)printf("%d", b[i]);
system("pause");
return 0;
}
一维差分(2)
//计算一维差分
//例题:在n个数中,进行q次操作,每次询问一个区间[l->r],使得区间中所有数加上一个数值c
//由已知数值序列A{a_1,a_2,a_3.....a_n}构造差分序列D{b_1,b_2,b_3.....b_n}使得a_n=b_1+b_2+.....+b_n;4
//公式:A[L->R]中每个数值+c <=> D[L]+c,D[R+1]-c
int D[1000] = { 0 };
void insert(int l, int r, int c) { D[l] += c, D[r + 1] -= c; }
void test02()
{
int A[1000] = { 0 };
int n, q, l, r, c;
cin >> n >> q;
for (int i = 1; i <= n; i++)//创建数值序列A并构造A的差分序列D
{
cin >> A[i];
insert(i, i, A[i]);
}
while (q--)
{
cin >> l >> r >> c;
insert(l, r, c);
}
for (int i = 1; i <= n; i++)
{
D[i] += D[i - 1];
cout << D[i] << " ";
}//将差分数组D做一次前缀求和就行
}
二维差分
代码实现:
给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
const int N = 1010;
int n, m, q;
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()
{
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &a[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; 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 - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
for (int i = 1; i <= n; i++)
for (int j = 1; j < m; j++)
printf("%d ", b[i][j]);
return 0;
}
二维差分(2)
//计算二维差分
/* 例题:在一个 n* m 的矩阵中进行q次操作,将(x_1, y_1)->(x_2, y_2)中的元素都加上数值c
即给以(x_1, y_1)为左上角,(x_2, y_2)为右下角的子矩阵中的所有元素加上c */
//由已知矩阵创建差分矩阵,原矩阵每个对应元素A(i,j)的值都等于以差分矩阵D(0,0)为起点D(i,j)为终点的子矩阵所有元素的值求和
//公式:D[x1][y1] += c; D[x1][y2 + 1] -= c; D[x2 + 1][y1] -= c; D[x2 + 1][y2 + 1] += c;
int D[100][100];
void insert(int x_1, int y_1, int x_2, int y_2,int c)
{
D[x_1][y_1] += c;
D[x_1][y_2 + 1] -= c;
D[x_2 + 1][y_1] -= c;
D[x_2 + 1][y_2 + 1] += c;
}
void test04()
{
int n, m, q;
int A[100][100] = { 0 };
cin >> n >> m >> q;
for(int x=1;x<=n;x++)
for (int y = 1; y <= m; y++)
{
cin >> A[x][y];
insert(x, y, x, y, A[x][y]);
}
while (q--)
{
int x_1, x_2, y_1, y_2, c;
cin >> x_1 >> y_1 >> x_2 >> y_2 >> c;
insert(x_1, y_1, x_2, y_2, c);
}
for (int x = 1; x <= n; x++)
{
for (int y = 1; y <= m; y++)
{
D[x][y] += D[x - 1][y] + D[x][y - 1] - D[x - 1][y - 1];
cout << D[x][y] << " ";
}
cout << endl;
}
return;
}