前缀和

前缀和是一种重要的预处理,能大大降低查询的时间复杂度。
最简单的一道题就是给定 n 个数和 m 次询问,每次询问一段区间的和。求一个 O(n + m) 的做法。
用 O(n) 前缀和预处理,O(m) 询问。
一、一维前缀和
主要代码

for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i];  //O(n)
while(m--)        //O(m) 
{
     int L, R; scanf("%d%d", &L, &R);
     printf("%d\n", sum[R] - sum[L - 1]);
}

二、二维前缀和
给定一个n*n的矩阵,找一个最大的子矩阵,使得这个子矩阵里面的元素和最大。

这道题最朴素的算法是 O(n6),用二维前缀和可以降到 O(n4)。
再想想前缀和矩阵怎么生成?看个图就明白了:
那么最大的矩形前缀和就等于蓝的矩阵加上绿的矩阵,再减去重叠面积,最后加上小方块,即
sum[i][j] = sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1] + a[i][j]
主要代码

for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
    sum[i][j] = sum[i - 1][j] + sum[i - 1][j] - sum[i - 1][j - 1] + a[i][j];
for(int i = 1; i <= n; ++i) //枚举矩阵左右端点
for(int j= 1; j <= n; ++j)
for(int k = i; K <= n; ++k)
for(int h = j; h <= n; ++h)
{
      tot = sum[k][h] - sum[i - 1][h] - sum[k][j - 1] + sum[i - 1][j - 1];  //同理矩阵生成
     ans = max(ans, tot);
}

B3612 【深进1.例1】求区间和

P4702 取石子(入门) 前缀和

P5638 【CSGRound2】光骓者的荣耀(普及-) 前缀和

P1147 连续自然数和(普及-) 枚举,前缀和,数学公式

 

posted @ 2022-03-06 21:40  心悟&&星际  阅读(50)  评论(0编辑  收藏  举报