分块实现的区间加,区间求和。(1152 ms)
1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 #define val(i) (v[i]+atag[bl[i]]) 5 using namespace std; 6 typedef long long ll; 7 8 ll bl[50010],sum[250],v[50010],atag[250]; 9 ll n,blo,opt,l,r,c; 10 11 void change(ll l,ll r,ll c){ 12 if(bl[l] == bl[r]){ 13 for(int i = l;i <= r;i++)v[i] += c; 14 sum[bl[l]] += (r-l+1)*c; return; 15 } 16 for(int i = l;i <= bl[l]*blo;i++)v[i] += c; 17 sum[bl[l]] += c*(bl[l]*blo-l+1); 18 for(int i = (bl[r]-1)*blo+1;i <= r;i++)v[i] += c; 19 sum[bl[r]] += c*(r-(bl[r]-1)*blo); 20 for(int i = bl[l]+1;i < bl[r];i++){ 21 atag[i] += c; 22 sum[i] += c*(min(bl[i]*blo,n)-max(0ll,(bl[i]-1)*blo)); 23 } 24 } 25 26 ll query(ll l,ll r,ll c){ 27 ll ans = 0; c++; 28 if(bl[l] == bl[r]){ 29 for(int i = l;i <= r;i++)ans += val(i),ans %= c; 30 return ans; 31 } 32 for(int i = l;i <= bl[l]*blo;i++)ans += val(i),ans %= c; 33 for(int i = (bl[r]-1)*blo+1;i <= r;i++)ans += val(i),ans %= c; 34 for(int i = bl[l]+1;i < bl[r];i++)ans += sum[i],ans %= c; 35 return ans; 36 } 37 38 int main(){ 39 scanf("%lld",&n);blo = sqrt(n); 40 for(int i = 1;i <= n;i++){ 41 scanf("%lld",&v[i]); 42 bl[i] = (i-1)/blo+1; 43 sum[bl[i]] += v[i]; 44 } 45 for(int i = 1;i <= n;i++){ 46 scanf("%lld%lld%lld%lld",&opt,&l,&r,&c); 47 switch(opt){ 48 case 0:change(l,r,c);break; 49 case 1:printf("%lld ",query(l,r,c));break; 50 } 51 } 52 return 0; 53 }
线段树(583 ms)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define mid (l+r>>1) 5 #define memid (me.l+me.r>>1) 6 #define me tree[p] 7 #define lc tree[p<<1] 8 #define rc tree[p<<1|1] 9 using namespace std; 10 typedef long long ll; 11 12 const ll Maxn = 50010; 13 14 struct Seg{ 15 ll l,r,w,t; 16 ll len(){return r-l+1;} 17 }tree[Maxn<<2]; 18 19 void build(ll p,ll l,ll r){ 20 me.l = l,me.r = r,me.t = 0; 21 if(l == r){scanf("%lld",&me.w);return;} 22 build(p<<1,l,mid),build(p<<1|1,mid+1,r); 23 me.w = lc.w+rc.w; 24 } 25 26 void down(ll p){ 27 lc.w += me.t*lc.len(),rc.w += me.t*rc.len(); 28 lc.t += me.t,rc.t += me.t; me.t = 0; 29 } 30 31 void change(ll p,ll l,ll r,ll x){ 32 if(l <= me.l&&me.r <= r){ 33 me.t += x; 34 me.w += me.len()*x; 35 return; 36 } 37 if(me.t)down(p); 38 if(l <= memid)change(p<<1,l,r,x); 39 if(memid < r)change(p<<1|1,l,r,x); 40 me.w = lc.w+rc.w; 41 } 42 43 ll query(ll p,ll l,ll r,ll mod){ 44 if(l <= me.l&&me.r <= r)return me.w%mod; 45 down(p); ll val = 0; 46 if(l <= memid)val += query(p<<1,l,r,mod); 47 if(memid < r)val += query(p<<1|1,l,r,mod); 48 return val%mod; 49 } 50 51 ll n,opt,l,r,c; 52 53 int main(){ 54 scanf("%lld",&n); build(1,1,n); 55 for(ll i = 1;i <= n;i++){ 56 scanf("%lld%lld%lld%lld",&opt,&l,&r,&c); 57 switch(opt){ 58 case 0:change(1,l,r,c);break; 59 case 1:printf("%lld ",query(1,l,r,c+1));break; 60 } 61 } 62 63 return 0; 64 }