数列分块入门 7 总结

在这里插入图片描述
这题只要做对了前面的东东,这题肯定能做对的。(* ̄︶ ̄)
只要设m[i]表示第i块整体要乘的数,p[i]表示第i块整体要加的数即可。

记得!在乘c的时候要把p也给乘了(自己想想为什么)

还有,在做左右两边凸出来的东西的话,要先把整块的m[bl[i]],p[bl[i]]都附上去,然后清空(m[bl[i]]=1,p[bl[i]]=0),否则会有意想不到的错误!!!

上标:

#include<cstdio>
#include<algorithm>
#include<cmath>
#define mo 10007
#define N 100010
using namespace std;
int n,st,a[N],bl[N],le[N],ri[N];
int m[321],p[321],opt,l,r,c;

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 update(int x)
{
	for (int i=le[x];i<=ri[x];i++)
		a[i]=(m[x]*a[i]+p[x])%mo;
	m[x]=1,p[x]=0;
}

void add(int l,int r,int c)
{
	update(bl[l]);
	for (int i=l;i<=min(ri[bl[l]],r);i++) a[i]+=c;
	if (bl[l]!=bl[r])
	{
		update(bl[r]);
		for (int i=le[bl[r]];i<=r;i++) a[i]+=c;
	}
	for (int i=bl[l]+1;i<=bl[r]-1;i++) p[i]+=c;
}

void cheng(int l,int r,int c)
{
	update(bl[l]);
	for (int i=l;i<=min(ri[bl[l]],r);i++) a[i]=a[i]*c%mo;
	if (bl[l]!=bl[r])
	{
		update(bl[r]);
		for (int i=le[bl[r]];i<=r;i++) a[i]=a[i]*c%mo;
	}
	for (int i=bl[l]+1;i<=bl[r]-1;i++)
		m[i]=m[i]*c%mo,p[i]=p[i]*c%mo;
}

int main()
{
	freopen("6283.in","r",stdin);
	freopen("6283.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;
		if (!le[bl[i]]) le[bl[i]]=i;
		ri[bl[i]]=i;
	}
	for (int i=1;i<=bl[n];i++) m[i]=1;
	for (int i=1;i<=n;i++)
	{
		opt=read(),l=read(),r=read(),c=read();
		if (opt==0) add(l,r,c);
		else if (opt==1) cheng(l,r,c);
		else printf("%d
",(a[r]*m[bl[r]]+p[bl[r]])%mo);
	}
	return 0;
}
转载需注明出处。
原文地址:https://www.cnblogs.com/jz929/p/11817612.html