分块 学习笔记

分块学习笔记

1)设置块的大小

sn=(int)sqrt(n);
if(n/sn>=MX) sn=n/MX;//MX为块的极限大小,若卡空间时用,这时数组与块数量有关的部分可以开小,与块大小有关的部分则要开大,注意。。

2)方便的函数

int loc(int x){//位置x属于哪一块
	return x/sn +1;//返回+1是空出第0块来,搞前缀和不用特判什么的
}

int getL(int x){//第x块左端点
	return max((x-1)*sn,1);//最左是1,要取max
}

int getR(int x){
	return min(x*sn-1,n);//最右是n,要取min
}

3)预处理信息

1)前缀块信息,每块n个信息$n\sqrt n \( 2)块到块信息,每块\)\sqrt n\(个信息\)(\sqrt n)^3=n\sqrt n \( 3)所某块的左端点到右边任意位置的信息,\)n\sqrt n \( 这个最好开\)\sqrt n \sqrt n \(数组,每块留一个0的空位,最后留一个sn的位置记整块总和 **可以\)O(\sqrt n)\(维护\)O(1)$询问解决单点修改区间查询问题*

4)获得答案

BL,BR表示第BL块-第BR块
L,R表示BL块的左端点及BR块的右端点
x, y为询问区间

BL=loc(x),BR=loc(y);
if(BL+1>=BR){//x,y在同一块/相邻两块直接扫过去统计
	for(i=x;i<=y;i++) xxx;
}
else{
	if(getL(BL)!=x) BL++;
	if(getR(BR)!=y) BR--;
	L=getL(BL);
	R=getR(BR);
	ans+=get(BL,BR);
	for(i=x;i<L;i++) xxx;
	for(i=y;i>r;i++) xxx;
}

5) 注意事项:

预处理数组时注意 初始化

posted @ 2017-02-24 10:09  _zwl  阅读(177)  评论(0编辑  收藏  举报