当前位置: 首页 > article >正文

蓝桥备赛(24)算法篇【前缀和】

一、前缀和

前缀和与差分的核心思想是   预处理 , 可以再暴力枚举的过程中 , 快速给出查询结果 , 从而优化时间复杂度。

是经典的用空间替换时间的做法 。

 

二、 一维前缀和

登录—专业IT笔试面试备考平台_牛客网

注意: 使用前缀和数组时候 , 下标必须从 1 开始计数 , 这样真的超级方便、简洁,规避了很多越界的情况 , 如果你下标从0开始 , 需要使用if 判断 ~

在来简述以下方法:

1.创建前缀和数组: f[i] = f[i − 1] + a[i] 

 2.查询 [l, r] 区间和: f[r] − f[l − 1]

#include <iostream>
using namespace std;

typedef long long LL;
const int N = 1e5 + 10;
LL a[N],f[N];//f[N]前缀和数组
int n,q; 

int main()
{
	cin >> n >> q;
	for(int i = 1;i<=n;i++)cin >> a[i];
	
	//处理前缀和数组
	for(int i = 1 ;i<=n;i++)
	{
		f[i] = f[i-1] + a[i];
	} 
	//处理q次询问
	while(q--)
	{
		int l,r;
		cin >> l >> r;
		cout << f[r] - f[l-1] << endl;
	 } 
	return 0;
}

三、最大字段和

P1115 最大子段和 - 洛谷

#include <iostream>
using namespace std;

typedef long long LL;
const int N = 2e5 + 10; 
int n;
LL f[N];//前缀和数组 
int main()
{
	
	cin >> n;
	for(int i = 1;i<=n;i++)
	{
		LL x;
		cin >> x;
		f[i] = f[i-1] + x;
	}
	
	//初始化为负的无穷大 
	//因为最小字段和也可能是负数 
	LL ret = -1e20;
	LL prevmin = 0;
	for(int i = 1;i<=n;i++)
	{
		ret = max(ret,f[i]-prevmin);
		prevmin = min(prevmin,f[i]);
	}
	cout << ret << endl;
	return 0;
}

四、二维前缀和

登录—专业IT笔试面试备考平台_牛客网

#include <iostream>
using namespace std;

typedef long long LL;
const int N = 1010;
int n,m,q;
LL f[N][N];

int main()
{
	cin >> n >> m >> q;
	for(int i = 1;i<=n;i++)
	{
		for(int j = 1;j<=m;j++)
		{
			LL x;cin >> x;
			f[i][j] = f[i-1][j] + f[i][j-1] - f[i-1][j-1] + x;
		}
	}
	//处理q次查询
	 while(q--)
	 {
	 	int x1,y1,x2,y2;
	 	cin >> x1 >> y1 >> x2 >> y2;
	 	cout << f[x2][y2] - f[x1-1][y2] - f[x2][y1-1]+f[x1-1][y1-1] << endl;
	 }
	return 0;
}

五、激光炸弹

P2280 [HNOI2003] 激光炸弹 - 洛谷

#include <iostream>
using namespace std;

const int N = 5010;
int n,m;
int a[N][N];
int f[N][N];//前缀和矩阵 

int main()
{
	cin >> n >> m;
	while(n--)
	{
		int x,y,v;
		cin >> x >> y >> v;
		x++,y++;//下标从1开始计数
		a[x][y] += v;//同一个位置,有可能存在多个目标
	}
	n = 5001;
	//预处理前缀和矩阵 
	for(int i = 1;i<=n;i++)
	{
		for(int j = 1;j<=n;j++)
		{
			f[i][j] = f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j];
		}
	}
	//枚举所有边长为m的正方形
	int ret = 0;
	m = min(m,n);//如果炸弹威力大,可以把整个区域全部都摧毁 
	for(int x2 = m;x2 <= n ; x2++)
	{
		for(int y2 = m ; y2 <= n;y2++)
		{
			int x1 = x2 - m +1;
			int y1 = y2 - m +1;
			ret = max(ret,f[x2][y2] - f[x1-1][y2] - f[x2][y1-1] + f[x1-1][y1-1]);
		}	
	} 
	cout <<ret << endl;
	return 0;
 } 

http://www.kler.cn/a/597106.html

相关文章:

  • 《虚拟战场的对决》
  • VLAN:逻辑隔离冲突网络的详细讲解
  • 行业分析---小鹏汽车2024全年财报
  • (C语言)typedef 讲解
  • (UI自动化测试)第二篇:元素定位的方法_class定位
  • Spring6:10 数据校验-Validation
  • 从投机到可持续发展:ETHDenver 2025 的关键启示!
  • JVM垃圾回收笔记02-垃圾回收器
  • Linux 通过压缩包安装 MySQL 并设置远程连接教程
  • Java替换jar包中class文件
  • 当AI重构编程范式:Java 24的进化逻辑与技术深水区的战略突围
  • 【IROS 2025】CMU提出路径规划器PIPE:机器人探索效率提升14.6%,地图准确率提高9.3%!
  • dfs(二十五)22. 括号生成
  • 【Golang】defer与recover的组合使用
  • 防火墙带宽管理
  • 《Python实战进阶》No29: 自动化部署工具:Ansible 与 Fabric
  • 宝塔平替!轻量级开源 Linux 管理面板 mdserver-web
  • 基于yolov11的防震锤缺陷检测系统python源码+pytorch模型+评估指标曲线+精美GUI界面
  • C++:背包问题习题
  • Linux 音频驱动 WM8960 音频 DAC IC 音乐播放与录音