【模板】树状数组 1
D e s c r i p t i o n Description Description
一个长度为
n
n
n的序列
a
,
a,
a,两种操作:
1.1
x
y
—
—
a
x
=
y
1.1\ x\ y——a_x = y
1.1 x y——ax=y
2.2
x
y
—
—
2.2\ x\ y——
2.2 x y——查询
∑
i
=
x
y
a
i
\sum_{i=x}^{y}a_i
∑i=xyai
S o l u t i o n Solution Solution
单点修改略(
区间查询:
[
l
,
r
]
[l,r]
[l,r]的区间和就是
(
[
1
,
r
]
([1,r]
([1,r]的区间和
)
−
(
)-(
)−(
[
1
,
l
−
1
]
[1,l-1]
[1,l−1]的区间和
)
)
)
A c c e p t e d c o d e Accepted\ code Accepted code
#include<cstdio>
using namespace std;
int n, m;
int t[500005];
void update(int x, int k) {
for (; x <= n; x += x & -x) t[x] += k;
}
int get_sum(int x) {
int res = 0;
for (; x; x -= x & -x) res += t[x];
return res;
}
int main() {
scanf("%d %d", &n, &m);
for (int x, i = 1; i <= n; ++i)
scanf("%d", &x), update(i, x);
for (int x, y, ok, i = 1; i <= m; ++i) {
scanf("%d %d %d", &ok, &x, &y);
if (ok == 1) update(x, y);
else printf("%d\n", get_sum(y) - get_sum(x - 1));
}
}
【模板】树状数组 2
D e s c r i p t i o n Description Description
一个长度为
n
n
n的序列
a
,
a,
a,两种操作:
区间修改,单点查询
S o l u t i o n Solution Solution
树状数组维护
a
a
a的差分数组
d
d
d
d
i
=
a
i
−
a
i
−
1
d_i=a_i-a_{i-1}
di=ai−ai−1 其中
a
0
=
0
a_0=0
a0=0
显然
a
i
=
∑
j
=
1
i
d
j
a_i = \sum_{j=1}^id_j
ai=∑j=1idj
所以单点查询求
∑
i
=
1
x
d
i
\sum_{i=1}^{x}d_i
∑i=1xdi
区间修改:
我们研究修改
[
l
,
r
]
[l,r]
[l,r]的值时
d
d
d会怎么变
假设
a
=
a=
a={
1
,
3
,
4
,
7
,
2
1,3,4,7,2
1,3,4,7,2}
则有
d
=
d=
d={
1
,
2
,
1
,
3
,
−
5
1,2,1,3,-5
1,2,1,3,−5}
假设我们给区间
[
2
,
4
]
[2,4]
[2,4]加上
2
2
2
则
a
=
a=
a={
1
,
5
,
6
,
9
,
2
1,5,6,9,2
1,5,6,9,2}
,
d
=
,d=
,d={
1
,
4
,
1
,
3
,
−
7
1,4,1,3,-7
1,4,1,3,−7}
显然当给区间
[
l
,
r
]
[l,r]
[l,r]加
k
k
k时
d
l
=
d
l
+
k
,
d
r
+
1
=
d
r
+
1
−
k
d_l=d_l+k,d_{r+1}=d_{r+1}-k
dl=dl+k,dr+1=dr+1−k
(易证
A c c e p t e d c o d e Accepted\ code Accepted code
#include<cstdio>
using namespace std;
int n, m;
int t[500005];
void update(int x, int k) {
for (; x <= n; x += x & -x) t[x] += k;
}
int get_sum(int x) {
int res = 0;
for (; x; x -= x & -x) res += t[x];
return res;
}
int main() {
scanf("%d %d", &n, &m);
for (int x, y = 0, i = 1; i <= n; ++i)
scanf("%d", &x), update(i, x - y), y = x;
for (int x, y, k, ok, i = 1; i <= m; ++i) {
scanf("%d %d", &ok, &x);
if (ok == 1) scanf("%d %d", &y, &k), update(x, k), update(y + 1, -k);
else printf("%d\n", get_sum(x));
}
}