One-dimensional: Make \ (v_i\) for the difference fraction Group, then \ ([0, k]\) prefix and is \ (\sum{v_i (k+1-i)} = (k+1) \cdot \sum{v_i} + \sum{v_i \cdot (-i)} \), the tree-like array is maintained for \ (v_i\) and \ (v_i \cdot i\) .
template <typename i>struct Fenwick {struct Node {I v0, v1; void Add (i d0, I d1) {v0 + = D0; V1 + = D1; } void operator + = (const Node &RHS) {v0 + = Rhs.v0; V1 + = RHS.V1; } }; Fenwick (int n): N (n), tree (n) {} void Orz (int k, i d0, I D1) {for (; k < n; k |= k + 1) {Tree[k ].add (D0, D1); }} void Add (int l, int r, I d) {//[L, R] Orz (L, D,-l * d); Orz (R,-D, R * d); } I sum (int k) {//[0, K] Node res = {}; for (int i = k; I >= 0; i = (I & (i + 1))-1) {res + = Tree[i]; } return (k + 1) * res.v0 + res.v1; } I sum (int l, int r) {//[L, R) return sum (r-1)-sum (L-1); } int n; Vector<node> tree;};
Two-dimensional: similar to one-dimensional derivation, maintenance \ (V (i,j) \) , \ (V (i,j) \cdot i\) , \ (V (i,j) \cdot j\) and \ (V (i,j) \cdot ij\) .
struct Fenwick {struct Node {int V, VI, VJ, Vij; void operator + = (const Node &RHS) {v + = RHS.V; VI + = RHS.VI; VJ + = RHS.VJ; Vij + = Rhs.vij; } void apply (int d, int di, int dj, int dij) {v + = D; VI + = di; VJ + = DJ; Vij + = Dij; } }; Fenwick (int n, int m): N (N), M (m), Tree (n, vector<node> (m)) {} void Add (int x, int y, int d) {int di =- X * D; int DJ =-Y * D; int dij = x * y * D; for (int i = x, i < n; I |= i + 1) {for (int j = y; j < M; J |= J + 1) {tree[i][j].apply (D, Di, DJ, DIJ); }}} int sum (int x, int y) {Node res = {}; for (int i = x; I >= 0, i = (I & (i + 1))-1) {for (int j = y; J >= 0; j = (J & (J + 1))-1) { Res + = Tree[i][j]; }} return (x + 1) * (y + 1) * rES.V + (y + 1) * RES.VI + (x + 1) * res.vj + Res.vij; } int n, m; vector< vector<node> > tree;};
Ceramic interval modification + interval summation tree array (one-dimensional/two-D)