学信奥来csp帮www.cspbang.com (http://www.cspbang.com)
前缀和是基础算法之一,它一般应用于快速求出某个连续区间的和。前缀和一般包括一维前缀和,二维前缀和,前缀和算法的时间复杂度是O(1)。
原数组:arr[8]={9, 3, 1, 7, 5, 6, 0, 8}
前缀和数组:qzh[8]={9, 12, 13, 20, 25, 31, 31, 39}
如果求3-5这个范围内的区间和 即: re = qzh[5]-qzh[2]=13; 与结果 1+7+5=13一致;
二维前缀和一样,只是数组从一维数组编程二维数组
arr[]是原数组, qzh[i]是前缀和数组,表示arr[]数组中从第一个元素到第i个元素的和,第一个元素可能是下标0,也可能是下标1,这取决于数组的读入
构建: qzh[i] = qzh[i-1]+arr[i];
使用: re = qzh[r]-qzh[l-1]; r和l是要求区间和的左右边界
arr[][]是原数组, qzh[i][j]是前缀和数组,表示arr[][]数组中从第一个元素到坐标(i,j)元素的和.第一个元素可能是下标(0,0),也可能是下标(1,1),这取决于二维数组的读入
构建: qzh[i][j] = qzh[i - 1][j] + qzh[i][j - 1] + arr[i][j] - qzh[i - 1][j - 1]
使用: 查询矩形内的元素和, 一般2个点可以确定一个矩形, 以(x1,y1),(x2,y2)为例, (x1,y1)是左上角,(x2,y2)为右下角,求矩形内元素和
re = qzh[x2][y2] - qzh[x1 - 1][y2] - qzh[x2][y1 - 1] + qzh[x1 - 1][y1 - 1]
P8772 [蓝桥杯 2022 省 A] 求和
题解思路 : 和可以进行合并成: a1*(a2+a3+…+an)+ a2*(a3+a4+…+an)…
AC代码
#include "iostream"
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
int main() {
ll n, arr[N], qzj[N];
ll re = 0;
cin >> n >> arr[0];
qzj[0] = arr[0];
for (int i = 1; i < n; ++i) {
cin >> arr[i];
qzj[i] = arr[i] + qzj[i - 1];
}
for (int i = 0; i < n; ++i) {
re = arr[i] * (qzj[n - 1] - qzj[i]) + re;
}
cout << re;
}
P1719 最大加权矩形
先构建二维前缀和数组,然后遍历查找
#include
using namespace std;
int n;
int a[137][137]; //原矩阵
int sum[137][137]; //存放二维前缀和
int main(int argc, char** argv) {
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
sum[i][j]=sum[i-1][j]+sum[i][j-1]+a[i][j]-sum[i-1][j-1]; //计算二维前缀和,并存入sum数组
}
}
int mx=-9999999; //寻找最大值,先定义一个最小值
for(int x1=1;x1<=n;x1++) //对矩阵进行遍历
{
for(int y1=1;y1<=n;y1++)
{
for(int x2=1;x2<=n;x2++)
{
for(int y2=1;y2<=n;y2++)
{
if(x2x1,y2>y1才可以
continue;
mx=max(mx,sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]); //寻找子区间的最大值
}
}
}
}
cout<