数列分块入门4(区间求和)

原题:https://loj.ac/problem/6280

题解:这题不太难,分块求区间和就行了。

#include
#define reg register
#define N 50001
#define M 300
#define ll long long
using namespace std;
int a[N],pos[N],n,m,s[M];
ll sum[M];
inline int rd(){
	int x=0;int f=1;char s=getchar();
	while(s>'9' || s<'0') f=(f=='-'?-1:f),s=getchar();
	while(s>='0' && s<='9') x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return x*f; 
}

inline int val(int x) {return a[x]+s[pos[x]];}
inline void add(int l,int r,ll c){
	for(reg int i=l;i<=min(r,pos[l]*m);i++) a[i]+=c,sum[pos[i]]+=c;
	if(pos[l]!=pos[r]){
		for(reg int i=(pos[r]-1)*m+1;i<=r;i++) a[i]+=c,sum[pos[i]]+=c;
	} 
	for(reg int i=pos[l]+1;i<=pos[r]-1;i++) sum[i]+=1ll*m*c,s[i]+=c;
}

inline ll query(int l,int r,ll c){
	ll ans=0;
	for(reg int i=l;i<=min(r,pos[l]*m);i++) ans=(ans+val(i))%c;
	if(pos[l]!=pos[r])
		for(reg int i=(pos[r]-1)*m+1;i<=r;i++) ans=(ans+val(i))%c;
	for(reg int i=pos[l]+1;i<=pos[r]-1;i++) ans=(ans+sum[i])%c; 
	return ans%c;
}
int main(){
//	freopen("input.in","r",stdin);
	n=rd();m=sqrt(n);
	for(reg int i=1;i<=n;i++) a[i]=rd(),pos[i]=(i-1)/m+1,sum[pos[i]]+=1ll*a[i];
	for(reg int i=1,opt,l,r,c;i<=n;i++){
		opt=rd();l=rd();r=rd();c=rd();
		if(opt==0) add(l,r,1ll*c);
		else printf("%d\n",query(l,r,c+1));
	}
	return 0;
} 

 

你可能感兴趣的:(分块)