[LOJ6280]数列分块入门 4
题目大意:
给你一个长度为$n(n\leq50000)$的序列$A$,支持进行以下两种操作:
1.将区间$[l,r]$中所有数加上$c$;
2.询问区间$[l,r]$在模$c+1$意义下的和。
思路:
分块。
1 #include<cmath> 2 #include<cstdio> 3 #include<cctype> 4 typedef long long int64; 5 inline int getint() { 6 register char ch; 7 register bool neg=false; 8 while(!isdigit(ch=getchar())) if(ch=='-') neg=true; 9 register int x=ch^'0'; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 11 return neg?-x:x; 12 } 13 const int N=50001; 14 int bel[N],begin[N],end[N]; 15 int64 val[N],tag[N],sum[N]; 16 inline int64 calc(const int &x) { 17 return val[x]+tag[bel[x]]; 18 } 19 inline void modify(const int &l,const int &r,const int &c) { 20 if(bel[l]==bel[r]) { 21 for(register int i=l;i<=r;i++) { 22 val[i]+=c; 23 sum[bel[i]]+=c; 24 } 25 return; 26 } 27 for(register int i=l;bel[i]==bel[l];i++) { 28 val[i]+=c; 29 sum[bel[i]]+=c; 30 } 31 for(register int i=r;bel[i]==bel[r];i--) { 32 val[i]+=c; 33 sum[bel[i]]+=c; 34 } 35 for(register int i=bel[l]+1;i<bel[r];i++) { 36 tag[i]+=c; 37 sum[i]+=c*(end[i]-begin[i]+1); 38 } 39 } 40 inline int query(const int &l,const int &r,const int &mod) { 41 int ret=0; 42 if(bel[l]==bel[r]) { 43 for(register int i=l;i<=r;i++) ret=(ret+calc(i))%mod; 44 return ret; 45 } 46 for(register int i=l;bel[i]==bel[l];i++) ret=(ret+calc(i))%mod; 47 for(register int i=r;bel[i]==bel[r];i--) ret=(ret+calc(i))%mod; 48 for(register int i=bel[l]+1;i<bel[r];i++) ret=(ret+sum[i])%mod; 49 return ret; 50 } 51 int main() { 52 const int n=getint(),block=sqrt(n); 53 for(register int i=1;i<=n;i++) { 54 val[i]=getint(); 55 bel[i]=i/block; 56 sum[bel[i]]+=val[i]; 57 if(!begin[bel[i]]) begin[bel[i]]=i; 58 end[bel[i]]=i; 59 } 60 for(register int i=0;i<n;i++) { 61 const int opt=getint(),l=getint(),r=getint(),&c=val[0]=getint(); 62 if(opt) { 63 printf("%d\n",query(l,r,c+1)); 64 } else { 65 modify(l,r,c); 66 } 67 } 68 return 0; 69 }