分块(Chunking)

分块的概念

分块(Chunking)是一种将数据或任务分解为更小的部分的思想,就是将一个区间分成几个块”。

分块算法的具体实现步骤

1.预处理部分

1.确定块的长度和块的数量

int len=sqrt(n),num=n/len;//n是总长,len是块长,num是块的数量
if(n%len!=0)num++;//n不能被len整除那么多余的要一个新的块

2. 预处理每个块的左端点和右端点

for(int i=1;i<=num;i++)//我写的是从1开始到n
{
   
   //L[i]是块i的左端点,R[i]是块i的右端点
	L[i]=(i-1)*len+1;//L[i]的上一个是R[i-1]也就是(i-1)*len
	R[i]=i*len;//R[i]是R[i-1]+len
}
R[num]=n;//特殊处理最后一个块的右端点

3. 预处理每个点在哪个块

for(int i=1;i<=num;i++)
{
   
   
	for(int j=L[i];j<=R[i];j++)//遍历块中的每个点
	{
   
   
		pos[j]=i;
	}
}

4. 预处理题目要求(示例为求区间总和)

for(int i=1;i<=num;i++)
{
   
   
	for(int j=L[i];j<=R[i];j++)
	{
   
   
		  sum[i]+=a[i];//a[i]为题目给定的值
	}
}

预处理部分完整代码:时间复杂度是 O ( n + n ) O(\sqrt{n}+n) O(n +n)

void init()
{
   
   
	int len=sqrt(n),num=n/len;
	if(n%len!=0)num++;
	for(int i=1;i<=num;i++)
	{
   
   
		L[i]=(i-1)*len+1;
		R[i]=i*len;
	}
	R[num]=n;
	for(int i=1;i<=num;i++)
	{
   
   
		for(int j=L[i];j<=R[i];j++)
		{
   
   
			  pos[i]+=a[j];
		}
	}
}

2.修改部分(区间增加k)

1.暴力修改

暴力查询散块,散块无法直接懒标记

void EA(int l,int r,int k)
{
   
   
	for(int i=l;i<=r;i++)
	{
   
   
		a[i]+=k;
	}
}

2.区间修改|最坏时间复杂度 O ( 3 n ) O(3\sqrt{n}) O(3n )

散块暴力,整块懒标记

void update(int l,int r,int k)
{
   
   
	int p=pos[l],q=pos[r];
	if(p==q)
	{
   
   
		EA(l,r,k);
	}
	else
	{
   
   
		EA(l,R[p]);//暴力散块
		EA(L[q],r);
		for(int i=p+1;i<=q+1;i++)//遍历整块
		{
   
   
			lazy[i]+=k;//不能覆盖之前的懒标记
		}
	}
}

3.查询部分

1.暴力查询

一样暴力查询散块

int query(int l,int r)//暴力查询的左端点和右端点
{
   
   
	int ans=0;
	for(int i=l<
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值