poj3468 A Simple Problem with Integers

思路1:

线段树区间更新。

实现:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 typedef long long ll;
 5 const int N = 100005;
 6 ll tree[N * 4], lazy[N * 4], a[N];
 7 int n, m;
 8 
 9 void build(int num, int l, int r)
10 {
11     if (l == r) { tree[num] = a[l]; return; }
12     int m = l + r >> 1;
13     build(num * 2, l, m);
14     build(num * 2 + 1, m + 1, r);
15     tree[num] = tree[num * 2] + tree[num * 2 + 1];
16 }
17 
18 void pushdown(int num, int cl, int cr)
19 {
20     if (!lazy[num]) return;
21     tree[num * 2] += lazy[num] * cl;
22     tree[num * 2 + 1] += lazy[num] * cr;
23     lazy[num * 2] += lazy[num];
24     lazy[num * 2 + 1] += lazy[num];
25     lazy[num] = 0;
26 }
27 
28 void update(int num, int l, int r, int x, int y, ll dx)
29 {
30     if (x <= l && y >= r) { tree[num] += (r - l + 1) * dx; lazy[num] += dx; return; }
31     int m = l + r >> 1;
32     pushdown(num, m - l + 1, r - m);
33     if (x <= m) update(num * 2, l, m, x, y, dx);
34     if (y >= m + 1) update(num * 2 + 1, m + 1, r, x, y, dx);
35     tree[num] = tree[num * 2] + tree[num * 2 + 1];
36 }
37 
38 ll query(int num, int l, int r, int x, int y)
39 {
40     if (x <= l && y >= r) return tree[num];
41     int m = l + r >> 1;
42     pushdown(num, m - l + 1, r - m);
43     ll ans = 0;
44     if (x <= m) ans += query(num * 2, l, m, x, y);
45     if (y >= m + 1) ans += query(num * 2 + 1, m + 1, r, x, y);
46     return ans;
47 }
48 
49 int main()
50 {
51     scanf("%d %d", &n, &m);
52     for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
53     getchar();
54     build(1, 1, n);
55     char tmp; int x, y; ll d;
56     for (int i = 0; i < m; i++)
57     {
58         scanf("%c", &tmp);
59         if (tmp == 'Q') { scanf("%d %d", &x, &y); getchar(); printf("%lld
", query(1, 1, n, x, y)); }
60         else { scanf("%d %d %lld", &x, &y, &d); getchar(); update(1, 1, n, x, y, d); }
61     }
62     return 0;
63 }

 思路2:

树状数组区间更新+区间查询。

http://blog.csdn.net/fsahfgsadhsakndas/article/details/52650026

实现:

 1 #include <cstdio>
 2 using namespace std;
 3 typedef long long ll;
 4 const int MAXN = 100005;
 5 ll bit0[MAXN], bit1[MAXN];
 6 int n, m;
 7 
 8 int lowbit(int x) { return x & -x; }
 9 
10 void add(ll * bit, int i, ll x)
11 {
12     while (i <= n) { bit[i] += x; i += lowbit(i); }
13 }
14 
15 ll sum(ll * bit, int i)
16 {
17     ll ans = 0;
18     while (i) { ans += bit[i]; i -= lowbit(i); }
19     return ans;
20 }
21 
22 ll query(int x)
23 {
24     return x * sum(bit0, x) - sum(bit1, x);
25 }
26 
27 int main()
28 {
29     scanf("%d %d", &n, &m);
30     char tmp; int x, y; ll d;
31     for (int i = 1; i <= n; i++) 
32     {
33         scanf("%lld", &d);
34         add(bit0, i, d);
35         add(bit0, i + 1, -d);
36         add(bit1, i, (i - 1) * d);
37         add(bit1, i + 1, -i * d);
38     }
39     getchar();
40     for (int i = 0; i < m; i++)
41     {
42         scanf("%c", &tmp);
43         if (tmp == 'Q') 
44         { 
45             scanf("%d %d", &x, &y); getchar();
46             ll r = query(y), l = query(x - 1);
47             printf("%lld
", r - l);
48         }
49         else 
50         { 
51             scanf("%d %d %lld", &x, &y, &d); getchar();
52             add(bit0, x, d);
53             add(bit0, y + 1, -d);
54             add(bit1, x, (x - 1) * d);
55             add(bit1, y + 1, -y * d);
56         }
57     }
58     return 0;
59 } 

 bit1的作用就是快速(O(logN))计算((j - 1) * c[j])(1 <= j <= i)的和。甚至换成单点更新的线段树也是行得通的。

 1 #include <cstdio>
 2 #include <iostream>
 3 using namespace std;
 4 typedef long long ll;
 5 const int MAXN = 100005;
 6 ll bit[MAXN], tree[MAXN * 4];
 7 int n, m;
 8 
 9 int lowbit(int x) { return x & -x; }
10 
11 void add(int i, ll x)
12 {
13     while (i <= n) { bit[i] += x; i += lowbit(i); }
14 }
15 
16 ll sum(int i)
17 {
18     ll ans = 0;
19     while (i) { ans += bit[i]; i -= lowbit(i); }
20     return ans;
21 }
22 
23 void update(int num, int l, int r, int x, ll dx)
24 {
25     if (l == r) { tree[num] += dx; return; }
26     int m = l + r >> 1;
27     if (x <= m) update(num * 2, l, m, x, dx);
28     else update(num * 2 + 1, m + 1, r, x, dx);
29     tree[num] = tree[num * 2] + tree[num * 2 + 1];
30 }
31 
32 ll query(int num, int l, int r, int x, int y)
33 {
34     if (x <= l && y >= r) return tree[num];
35     int m = l + r >> 1;
36     ll ans = 0;
37     if (x <= m) ans += query(num * 2, l, m, x, y);
38     if (y >= m + 1) ans += query(num * 2 + 1, m + 1, r, x, y);
39     return ans;
40 }
41 
42 ll get_ans(int x)
43 {
44     if (x < 1) return 0;
45     return x * sum(x) - query(1, 1, n + 1, 1, x);
46 }
47 
48 int main()
49 {
50     scanf("%d %d", &n, &m);
51     char tmp; int x, y; ll d;
52     for (int i = 1; i <= n; i++) 
53     { 
54         scanf("%lld", &d);
55         add(i, d); add(i + 1, -d);
56         update(1, 1, n + 1, i, (i - 1) * d); 
57         update(1, 1, n + 1, i + 1, -i * d); 
58     }
59     getchar();
60     for (int i = 0; i < m; i++)
61     {
62         scanf("%c", &tmp);
63         if (tmp == 'Q') 
64         { 
65             scanf("%d %d", &x, &y); getchar();
66             ll r = get_ans(y); 
67             ll l = get_ans(x - 1);
68             printf("%lld
", r - l);
69         }
70         else 
71         { 
72             scanf("%d %d %lld", &x, &y, &d); getchar();
73             add(x, d);
74             add(y + 1, -d);
75             update(1, 1, n + 1, x, ((ll)x - 1) * d);
76             update(1, 1, n + 1, y + 1, -(ll)y * d);
77         }
78     }
79     return 0;
80 } 
原文地址:https://www.cnblogs.com/wangyiming/p/8450421.html