专题5-1 分块:数组分块

本文介绍了分块思想在数组操作中的应用,通过分块提高时间空间效率。详细阐述了如何处理区间加法、单点查值、区间查值以及涉及乘法的复杂操作,并给出了相关例题和优化策略,例如选取k=√n时代价最低。
摘要由CSDN通过智能技术生成

专题5-1 分块:数组分块

http://hzwer.com/8053.html 此博客有部分借鉴内容,对原作者表示感谢

PART 1 分块简介

对于分块,许多人可能不陌生,毕竟这是一个顾名思义的词语。
不过,作为一个教学贴,有必要和大家介绍一下分块的概念。

分块,顾名思义就是将要求的东西分成若干个部分,对于特定的区间进行特定的操作

老子曾说过,任何事情都有联系
老子:“我没有说过。”

线段树和分块有相似之处,我们来类比一下
线段树

可以看出,对于一个1-5的数组,我们把它分成若干部分,直到叶节点所代表的区间大小为1
综合时间空间复杂度考虑,我们每次把区间二分,所需要的代价最小

如果我们现在要对1-4的区间进行统一操作,按照朴素算法,我们会对1-4中间的每一个区间都进行一次操作。

听起来不错,但是如果有100000次操作,100000个元素呢?这波肯定要爆掉。

于是,按照我们上面进行的操作,我们只需对1-3区间和4-4区间进行操作就可以了。

这就包含了分块的思想,分而治之

PART 2 分块简单举例

综上所述,我们要对数组进行分块,从而提高它的时间空间效率

Q1 给出一个长为n的数列,以及m个操作,操作涉及区间加法,单点查值。

对于这个题目,我们利用上面的操作,将数组进行以下操作

1.将数组分成k块
专题5-1.1
2.对于一个区间 [ l , r ] 来说,如果我们对其进行区间加法操作,我们就要分成两种操作

(1)如果说我们的边界 l 和 r 都在区间端点上,那就好办了,我们只需要给这些被包括的区间增加一个标记即可。

如果我们设定一个tag数组,存储一个数是否有过修改

但是,这里的tag数组肯定不能直接以元素下标进行创建,如果这样就和朴素算法没有什么区别,在这里,就是我们优化的精髓之一

我们用 bl [ i ] 存储下标为 i 的元素在第几个块内,如果我们要对一个区间进行操作,我们只要把 tag [ bl [ i ] ] 进行一次操作即可

(2)如果我们的边界 l 和 r 在不在边界而各在一个区间内呢?
专题5-1.2
对于 l 和 r 之间的区间(也就是第二部分),我们仍然可以采用类似(1)中的方法,接下来操作的就是对于 l 到 l 所在区间的终点和 r 区间的起点到 r 这些(也就是第一和第三部分),我们只要暴力操作就可以了

这样,我们的问题就解决了

等等,还有一个呢? 不是把数组分成k块吗?k怎么取?

根据各种各样的不等式,我们可以认为,当k=√n(根号n)的时候,时间空间复杂度代价最低

//数组分块1 区间修改,单点查询 
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,kt,m;
int v[50005],bl[50005],atag[50005];
void add(int a,int b,int c)
{
   
    for(int i=a;i<=min(bl[a]*kt,b);i++)//bl[a]*blo为a所在区间的终位,b为要替换的终位
	//这是对首区间的操作 
        v[i]+=c;
    if(bl[a]!=bl[b])
        for(
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值