学习笔记:分块

分块算法是一种优化后的暴力解法,适用于区间查询和更新问题。通过将序列分块,部分块完全在区间内时使用线段树策略处理,部分块则进行暴力更新。文章介绍了如何确定块大小,以及区间更新和查询的具体步骤,并提供了两道相关例题以加深理解。

前言

分块可以解决几乎全部的区间查询区间更新等问题,功能比线段树和树状数组要强大,但是时间复杂度会更大一点。其实分块就是一种优化过的暴力,它是对于整体进行像线段树一样的维护,对局部进行暴力的修改。

原理

顾名思义分块分块,我们把长度为n的序列分为若干块。维护块内信息即可。
又要问了,要多大呢?通常将块的大小设为 n \sqrt n n ,用pos数组储存每个块的位置。
最后分完有剩,那么剩余的单独为一个块。
在这里插入图片描述

我们用线段树的例题来介绍传送门luoguP3372

题目要求:
1.区间更新:
我们找在这个区间有多少个块是全部在里面的,因为这些块全要更新,我们可以添加懒惰标记,下次要用时才更新。
对于部分在区间的块,我们只有暴力的把这些在区间内的点更新即可、
2.区间查询:
还是讨论如果被区间包含的块,就直接加上处理懒标的值和之前的和即可。
部分在区间的块,就暴力计算值即可。

代码非常简单。也好理解。

#include<bits/stdc++.h>
using namespace std;
#define int long long

const int N=1e5+5;
int n,m,a[N];
int pos[N],sum[N],L[N],R[N],lz[N];
//块的位置,块的和,块的左区间和右区间,懒惰标记 

inline void build()
{
   
   	
	int t=sqrt(n*1.0);
	int num=n/t;
	if(n%t) num++;//如果有剩余,再加一个块 
	for(int i=1;i<=num;i++)
	{
   
   
		L[i]=(i-1)*t+1;//每个块的范围 
		R[i]=i*t;
	}
	R[num]=n;//最后一个块的右区间是n 
	
	for(int i=1;i<=num;i++)
		for(int j=L[i];j<=R[i];j++)
		{
   
   
			pos[j]=i;//该点属于哪个块 
			sum[i]+=a[j];//统计和 
		}
}

inline 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值