P3372 【模板】线段树 1

P3372 【模板】线段树 1

线段树

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1e5+5;
 5 ll a[maxn], add[maxn*4], sum[maxn*4];
 6 ll n, m;
 7 void pushup(int rt) {
 8     sum[rt] = sum[rt*2]+sum[rt*2+1];
 9 }
10 void pushdown(int rt, int l, int r) {
11     int mid = (l+r)/2;
12     sum[rt*2] = sum[rt*2]+add[rt]*(mid-l+1);
13     sum[rt*2+1] = sum[rt*2+1]+add[rt]*(r-mid);
14     add[rt*2] = add[rt*2]+add[rt];
15     add[rt*2+1] = add[rt*2+1]+add[rt];
16 
17     add[rt] = 0;
18 }
19 void build(int l, int r, int rt) {
20     add[rt] = 0;
21     if (l == r) {
22         sum[rt] = a[l];
23         return;
24     }
25     int mid = (l+r)/2;
26     build(l,mid,rt*2);
27     build(mid+1,r,rt*2+1);
28     pushup(rt);
29 }
30 void update(int be, int ed, int val, int l, int r, int rt) {
31     if (be <= l && r <= ed) {
32         add[rt] = add[rt]+val;
33         sum[rt] = sum[rt]+val*(r-l+1);
34         return;
35     }
36     pushdown(rt,l,r);
37     int mid = (l+r)/2;
38     if (be <= mid) update(be,ed,val,l,mid,rt*2);
39     if (ed > mid) update(be,ed,val,mid+1,r,rt*2+1);
40     pushup(rt);
41 }
42 ll query(int be, int ed, int l, int r, int rt) {
43     if (be <= l && r <= ed) {
44         return sum[rt];
45     }
46     pushdown(rt,l,r);
47     ll res = 0; int mid = (l+r)/2;
48     if (be <= mid) res += query(be,ed,l,mid,rt*2);
49     if (ed > mid) res += query(be,ed,mid+1,r,rt*2+1);
50     return res;
51 }
52 int main() {
53     scanf("%d%d",&n,&m);
54     for (int i = 1; i <= n; i++) scanf("%lld",&a[i]);
55     build(1,n,1);
56     while (m--) {
57         int op, x, y; scanf("%d%d%d",&op,&x,&y);
58         if (op == 1) {
59             int k; scanf("%d",&k);
60             update(x,y,k,1,n,1);
61         }
62         else {
63             ll ans = query(x,y,1,n,1);
64             printf("%lld\n",ans);
65         }
66     }
67     return 0;
68 }

 分块

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm> 
 4 #include <cmath>
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn = 1e5+5;
 8 int L[maxn], R[maxn];  // 每个区间的范围
 9 int pos[maxn];  // 记录所属块
10 ll sum[maxn], a[maxn];
11 ll add[maxn];  // lazy标记
12 
13 void change(int l, int r, int v) {
14     int p = pos[l], q = pos[r];
15     if (p == q) {  // 如果属于同一块
16         for (int i = l; i <= r; i++) a[i] += v;
17         sum[p] += (ll)(r-l+1)*v;
18     }
19     else {
20         for (int i = p+1; i <= q-1; i++) add[i] += v;  // p和q中间的块的add 
21         for (int i = l; i <= R[p]; i++) a[i] += v;
22         sum[p] += (ll)(R[p]-l+1)*v;
23         for (int i = L[q]; i <= r; i++) a[i] += v;
24         sum[q] += (ll)(r-L[q]+1)*v;
25     }
26 }
27 ll query(int l, int r) {
28     int p = pos[l], q = pos[r];
29     ll ans = 0;
30     if (p == q) {
31         for (int i = l; i <= r; i++) ans += a[i];
32         ans += add[p]*(r-l+1);
33     }
34     else {
35         for (int i = p+1; i <= q-1; i++) ans += sum[i] + add[i]*(R[i]-L[i]+1);
36         for (int i = l; i <= R[p]; i++) ans += a[i];
37         ans += add[p]*(R[p]-l+1);
38         for (int i = L[q]; i <= r; i++) ans += a[i];
39         ans += add[q]*(r-L[q]+1);
40     }
41     return ans;
42 }
43 
44 int main() {
45     int n, q; scanf("%d%d",&n,&q);
46     for (int i = 1; i <= n; i++) scanf("%lld",&a[i]);
47     int t = sqrt(n);
48     for (int i = 1; i <= t; i++) {
49         L[i] = (i-1)*t + 1;
50         R[i] = i*t;
51     }
52     if (R[t] < n) t++, L[t] = R[t-1]+1, R[t] = n;
53     for (int i = 1; i <= t; i++) {
54         for (int j = L[i]; j <= R[i]; j++) {
55             pos[j] = i;
56             sum[i] += a[j];
57         }
58     }
59     while (q--) {
60         int op, l, r, v;
61         scanf("%d",&op);
62         if (op == 2) {
63             scanf("%d%d",&l,&r);
64             printf("%lld\n",query(l,r));
65         }
66         else {
67             scanf("%d%d%d",&l,&r,&v);
68             change(l,r,v);
69         }
70     }
71     return 0;
72 }

 

posted @ 2019-10-23 17:05  麻辣猪仔  阅读(172)  评论(0编辑  收藏  举报