数列分块入门 1 总结

Question:

在这里插入图片描述
这题分块在这里插入图片描述
这里的删除线有点毒瘤啊。。。
我们设一个block[]表示第i位属于哪个块。
我们便可以这样子打:

	st=sqrt(n);
	for (int i=1;i<=n;i++) bl[i]=(i-1)/st+1;

然后,对于opt==0
我们发现它除了整个块,但两边可能会有一点点的多出来(就是不够一整个块)
这两边我们可以暴力搞,而中间的,我们便存一个b[]表示第i块整体加了多少。

	for (int i=l;i<=min(bl[l]*st,r);i++) a[i]+=c;
	if (bl[l]!=bl[r])
		for (int i=(bl[r]-1)*st+1;i<=r;i++) a[i]+=c;
	for (int j=bl[l]+1;j<=bl[r]-1;j++) b[j]+=c;

对于opt==1
呵呵,简单,直接输出a[r]+b[block[r]] 即可。

完整代码如下:

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,a[50010],b[231],opt,l,r,c,st;
int bl[50010];

inline int read()
{
	int x=0,f=0; char c=getchar();
	while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return f ? -x:x;
}

void add(int l,int r,int c)
{
	for (int i=l;i<=min(bl[l]*st,r);i++) a[i]+=c;
	if (bl[l]!=bl[r])
		for (int i=(bl[r]-1)*st+1;i<=r;i++) a[i]+=c;
	for (int j=bl[l]+1;j<=bl[r]-1;j++) b[j]+=c;
}

int main()
{
	freopen("6277.in","r",stdin);
	freopen("6277.out","w",stdout);
	n=read();st=sqrt(n);
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=1;i<=n;i++) bl[i]=(i-1)/st+1;
	for (int i=1;i<=n;i++)
	{
		opt=read(),l=read(),r=read(),c=read();
		if (opt==0) add(l,r,c);
		else printf("%d\n",a[r]+b[bl[r]]);
	}
	return 0;
}
posted @ 2019-01-24 21:13  jz929  阅读(100)  评论(0编辑  收藏  举报