---分块---

本文介绍了一种利用分块技术进行优雅的暴力搜索,适用于区间查询问题。通过将数组分为n*sqrt(n)大小的块,并预处理每个块的最值,可以在查询时快速获取区间内的最大值。代码示例展示了如何实现这一方法,并指出分块不仅限于解决特定问题,还可以用于维护多种数据结构。
摘要由CSDN通过智能技术生成

例题

分块就是优雅的暴力搜索,就是把这一个数组分成好多块,每一块预处理最值,区间查询时,取这个区间里的每个块的最值,然后再求那些块覆盖不到的地方的最值(这个步骤暴力就行)

显然块的数量和块的大小不能太大也不能太小,所以我们把块的大小取 n \sqrt{n} n ,代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rp(i, e) for(int i=1;i<=(e);i++)
#define pr(i, e) for(int i=(e);i>=1;i--)
#define rp0(i, e) for(int i=0;i<(e);i++)
#define pr0(i, e) for(int i=(e-1);i>=0;i--)
#define rps(i, b, e) for(int i=(b);i<=(e);i++)
#define prs(i, e, b) for(int i=(e);i>=(b);i--)
#define rpg(i, x) for(int i=head[x];i;i=e[i].nxt)
using namespace std;
const int NR=1e5+10;
typedef long long LL;
int n, T, l, r, qm, bn, block[NR];
//qm-->每一个块的大小
//bn-->块的数量
//block[i]-->a[i]所属的块的编号
LL a[NR];
LL s[NR];//每一个块的最大值
inline int query(int l, int r)
{
	int bl, br;
	LL res=-1e18;
	rp(i, bn)
	{
		bl=(i-1)*qm+1, br=min(i*qm, n);//块的左右元素
		if(br<l)continue;
		if(bl>r)break;
		if(bl>=l && br<=r)res=max(res, s[i]);
		else if(bl<l && br<=r)
			rps(j, l, br)res=max(res, a[j]);
		else rps(j, bl, r)res=max(res, a[j]);
	}
	return res;
}
int main()
{
	scanf("%d%d", &n, &T);
	qm=sqrt(n);
	bn=n/qm+bool(n%qm);
	memset(s, -999999, sizeof(s));
	rp(i, n)
	{
		scanf("%lld", a+i);
		block[i]=(i-1)/qm+1;
		s[block[i]]=max(s[block[i]], a[i]);
	}
	while(T--)
	{
		scanf("%d%d", &l, &r);
		printf("%d\n", query(l, r));
	}
    return 0;
}

80 pts ,虽然分块并不是专门用于 RMQ 和 RSQ ,但是可以维护很多别的东西

分块本质上还是一棵树,第一层是所有的树的集合,第二层是每一个块,第三层是每一个元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值