数列分块入门4(区间求和)
原题:https://loj.ac/problem/6280
题解:这题不太难,分块求区间和就行了。
#include<bits/stdc++.h>
#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;
}