题目:题目链接
题意:
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.The second line contains N numbers,
the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.Each of the next Q lines
represents an operation."C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
就是区间更新,求区间总和sum,树状数组(或者线段树):
Sum[x] = SUM(A[i], i=1...x)+(x+1)*SUM(delta[i],i=1...x)-SUM(i*delta[i],i=1...x)在成段更新时,是对delta
数组进行更新,于是用两个树状数组t1,t2来维护两个前缀和SUM(delta[i],i=1...x),SUM(i*delta[i],i=1...x),而
SUM(A[i], i=1...x)在更新过程中是不变的,所以可以预处理在数组中将区间的成段更新转化成对t1,t2两个树状数
组的单点更新,使更新复杂度保持O(log(n))
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100#include <iostream> #include <cstdio> #include <string> #include <string.h> #include <map> #include <vector> #include <cstdlib> #include <algorithm> #include <cmath> #include <queue> #include <set> #include <stack> #include <functional> #include <fstream> #include <sstream> #include <iomanip> #include <numeric> #include <cassert> #include <bitset> #include <stack> #include <ctime> #include <list> #define INF 0x7fffffff #define max3(a,b,c) (max(a,b)>c?max(a,b):c) #define min3(a,b,c) (min(a,b)<c?min(a,b):c) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; #define maxn 100005 __int64 sum[maxn]; __int64 t1[maxn]; __int64 t2[maxn]; inline __int64 lowbit(int x) { return (-x)&x; } inline void update(__int64 a[], int x, __int64 c) { while(x <= maxn) { a[x] += c; x += lowbit(x); } } inline __int64 getSum(__int64 a[], int x) { __int64 sum0 = 0; while(x) { sum0 += a[x]; x -= lowbit(x); } return sum0; } //根据公式Sum[x] = SUM(A[i], i=1...x)+(x+1)*SUM(delta[i],i=1...x)-SUM(i*delta[i],i=1...x)求Sum[x] __int64 Sum(__int64 t1[], __int64 t2[], int x) { __int64 res = sum[x]; res += (x+1)*getSum(t1, x); res -= getSum(t2, x); return res; } int main() { int n, q, tmp; mem(t1, 0); mem(t2, 0); scanf("%d%d", &n, &q); for(int i = 1; i <= n; ++i) { scanf("%d", &tmp); sum[i] = sum[i-1] + tmp; } while(q--) { __int64 suma, sumb; char ch; int a, b, c; getchar(); scanf("%c", &ch); if(ch == 'Q') { scanf("%d%d", &a, &b); suma = Sum(t1, t2, a-1); sumb = Sum(t1, t2, b); printf("%I64dn", sumb - suma); } else { scanf("%d%d%d", &a, &b, &c); update(t1, a, c);//更新SUM(delta[i],i=1...x)中的delta[a] update(t2, a, a*c);//更新SUM(i*delta[i],i=1...x)中的delta[a] //这两个update后,区间A[a...n]每个数都增加了c。 update(t1, b+1, -c);//这两个update后,区间A[b+1...n]每个数都减少了c,完成对区间A[a...b]的更新 update(t2, b+1, -(b+1)*c); } } return 0; }
还是要学习线段树/树状数组.....
最后
以上就是花痴鸡最近收集整理的关于POJ3468树状数组的全部内容,更多相关POJ3468树状数组内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复