Problem6695--树状数组 3 :区间修改,区间查询

6695: 树状数组 3 :区间修改,区间查询

[Creator : ]
Time Limit : 3.000 sec  Memory Limit : 512 MiB

Description

这是一道模板题。
给定数列 $a_1,a_2,...,a_n$,你需要依次进行 $q$ 个操作,操作有两类:
  • 1 l r x:给定 $l,r,,x$,对于所有 $i \in [l,r]$,将 $a_i$ 加上 $x$(换言之,将 $a_l,a_{l+1},...,a_r$ 分别加上 $x$);
  • 2 l r:给定 $l,r$,求 $\sum_{i=1}^{r}a_i$ 的值(换言之,求 $a_l+a_{l+1}+...+a_r$ 的值)。

说明

基于树状数组 2 的“差分”思路,考虑一下如何在该构建的树状数组中求前缀和:
位置 $p$ 的前缀和 = $\sum_{i=1}^p {a[i]}=\sum_{i=1}^p \sum_{j=1}^i {d[j]}$,在等式最右侧的式子中 $\sum_{i=1}^p \sum_{j=1}^i {d[j]}$ 中,$d[1]$ 使用了 $p$ 次,$d[2]$ 使用了 $p-1$ 次,$\cdots$。这样我们可以得到:
位置 $p$ 的前缀和 = $\sum_{i=1}^p \sum_{j=1}^i {d[j]} = \sum_{i=1}^{p} d[i] * (p-i+1)=(p+1)*\sum_{i=1}^p d[i] - \sum_{i=1}^p d[i]*i$。
这样,我们可以维护两个数组的前缀和:
  • 一个数组是 $sum_1[i] = d[i]$;
  • 一个数组是 $sum_2[i] = d[i]*i$。

查询

位置 $p$ 的前缀和是:$(p+1)*sum_1$ 数组中的 $p$ 的前缀和 - $sum_2$ 数组中的 $p$ 的前缀和。
区间 $[l,r]$ 的和是:位置 $r$ 的前缀和 - 位置 $l$ 的前缀和。

修改

对于 $sum_1$ 数组的修改问题等同于问题 2 中对 $d$ 数组修改。
对于 $sum_2$ 数组的修改也是类似,我们给 $sum_2[i]$ 加上 $l*x$,给 $sum_2[r+1]$ 减去 $(r+1)*x$。

Input

第一行包含 $2$ 个正整数 $n,q$,表示数列长度和询问个数。保证 $1 \leq n,q \leq 10^6$。
第二行 $n$ 个整数 $a_1,a_2,...,a_n$,表示初始数列。保证 $|a_i| \leq 10^6$。
接下来 $q$ 行,每行一个操作,为以下两种之一:
  • 1 l r x:给定 $l,r,,x$,对于所有 $i \in [l,r]$,将 $a_i$ 加上 $x$
  • 2 l r:给定 $l,r$,求 $\sum_{i=1}^{r}a_i$ 的值。
保证  $1 \leq l \leq r \leq n,\ |x| \leq 10^6$。

Output

对于每个 2 l r 操作,输出一行,每行有一个整数,表示所求的结果。

Sample 1 Input

5 10
2 6 6 1 1
2 1 4
1 2 5 10
2 1 3
2 2 3
1 2 2 8
1 2 3 7
1 4 4 10
2 1 2
1 4 5 6
2 3 4

Sample 1 Output

15
34
32
33
50

Source/Category

数据结构 2.10.树状数组