Advanced Data Structures :: Segment Tree
Description
敌人的军队驻扎在各个营地里,告诉你各个营地里有多少人,
请计算从第i个营地到第j个营地一共有多少人。
同时,敌人营地里的人数可能发生改变,因此会有三种操作——增加、减少、询问。
输出每次询问的结果。
Type
Advanced Data Structures :: Segment Tree
Advanced Data Structures :: Binary Indexed Tree
Analysis
经典的线段树题目, 也是经典的树状数组的题目。可以用线段树和树状数组两种方法来实现。
数状数组和线段树相比,复杂度相当,但是常数更小,速度更快、空间消耗更小,且编程复杂度较低。
但数状数组没有线段树功能那么的强大,例如无法求解RMQ问题。
Solution
1. Segment Tree
// HDOJ 1166 // 敌兵布阵 // by A Code Rabbit #include <cstdio> #include <cstring> #define LSon(x) (x << 1) #define RSon(x) (x << 1 | 1) const int MAXN = 50002; const int ROOT = 1; struct Seg{ int w; }; struct SegTree { Seg node[MAXN << 2]; void Update(int pos) { node[pos].w = node[LSon(pos)].w + node[RSon(pos)].w; } void Build(int l, int r, int pos) { if (l == r) { scanf("%d", &node[pos].w); return; } int m = l + r >> 1; Build(l, m, LSon(pos)); Build(m + 1, r, RSon(pos)); Update(pos); } void Modify(int l, int r, int pos, int x, int y) { if (l == r) { node[pos].w += y; return; } int m = l + r >> 1; if (x <= m) Modify(l, m, LSon(pos), x, y); else Modify(m + 1, r, RSon(pos), x, y); Update(pos); } int Query(int l, int r, int pos, int x, int y) { if (x <= l && r <= y) return node[pos].w; int m = l + r >> 1; int res = 0; if (x <= m) res += Query(l, m, LSon(pos), x, y); if (y > m) res += Query(m + 1, r, RSon(pos), x, y); return res; } }; int n; char cmd[20]; int x, y; SegTree tree; int main() { int tot_case = 0; scanf("%d", &tot_case); for (int t = 0; t < tot_case; t++) { scanf("%d", &n); tree.Build(1, n, ROOT); printf("Case %d:\n", t + 1); while (1) { getchar(); scanf("%s", cmd); if (!strcmp(cmd, "Add")) { scanf("%d%d", &x, &y); tree.Modify(1, n, ROOT, x, y); } else if (!strcmp(cmd, "Sub")) { scanf("%d%d", &x, &y); tree.Modify(1, n, ROOT, x, -y); } else if (!strcmp(cmd, "Query")) { scanf("%d%d", &x, &y); printf("%d\n", tree.Query(1, n, ROOT, x, y)); } else if (!strcmp(cmd, "End")) { break; } } } return 0; }
// HDOJ 1166 // 敌兵布阵 // by A Code Rabbit #include <cstdio> #include <cstring> const int MAXN = 50002; struct Bit { int c[MAXN], n; void Init(int x) { memset(c, 0, sizeof(c)); n = x; } void Add(int x, int y) { while (x <= n) { c[x] += y; x += x & -x; } } int Sum(int x) { int res = 0; while (x > 0) { res += c[x]; x -= x & -x; } return res; } }; int n; int a[MAXN]; char command[10]; int p, q; Bit bit; int main() { int tot_case; scanf("%d", &tot_case); for (int t = 0; t < tot_case; t++) { scanf("%d", &n); bit.Init(n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); bit.Add(i + 1, a[i]); } printf("Case %d:\n", t + 1); while (scanf("%s", command) && strcmp(command, "End") != 0) { scanf("%d%d", &p, &q); if (strcmp(command, "Add") == 0) bit.Add(p, q); else if (strcmp(command, "Sub") == 0) bit.Add(p, -q); else if (strcmp(command, "Query") == 0) printf("%d\n", bit.Sum(q) - bit.Sum(p - 1)); } } return 0; }