LOJ #6280. 数列分块入门 4

分块实现的区间加,区间求和。(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 }
原文地址:https://www.cnblogs.com/Wangsheng5/p/11785104.html