Advanced Data Structures :: Segment Tree
Description
Dota中的屠夫有个技能可以伸出一个钩子。
当然,这个和题目一点关系都没有。
一个钩子,可以被看成是好几节的金属节链接起来的。
最初钩子每节都是铜造的,一节铜是价值1。
之后,我们去改变某一段钩子的材料,变成银(价值2)或者金(价值3),或者变回铜。
输入钩子的长度,和如何去改变。
输出最后钩子的总价值。
Type
Advanced Data Structures :: Segment Tree
Analysis
经典的线段树,成段更新,需要用延迟标记。
如果对于每次更新,我们都化为每点去更新的话,时间复杂度会变成O(n)。
效率会降低,失去了使用线段树的意义(把n变成log n)。
但是我们可以利用延迟标记。
就是说,我们每次都更新到我们需要的值,便不再继续更新下去。
然后把需要更新下去的值记录下来。
下次如果要访问更深层次的节点,才会继续更新下去。
这样,就可以仅仅在需要的时候更新,让更新随着修改值,或者询问值的过程进行。
时间复杂度就依然为O(log n)。
Solution
// HDOJ 1698 // Just a Hook // by A Code Rabbit #include <cstdio> #define LSon(x) ((x) << 1) #define RSon(x) ((x) << 1 | 1) const int MAXN = 100002; const int ROOT = 1; struct Seg { int w; int flag; }; 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) { node[pos].flag = 0; if (l == r) { node[pos].w = 1; return; } int m = l + r >> 1; Build(l, m, LSon(pos)); Build(m + 1, r, RSon(pos)); Update(pos); } void Push(int l, int r, int pos) { Seg& father = node[pos]; Seg& lson = node[LSon(pos)]; Seg& rson = node[RSon(pos)]; if (father.flag) { int m = l + r >> 1; lson.w = father.flag * (m + 1 - l); rson.w = father.flag * (r - m); lson.flag = rson.flag = father.flag; father.flag = 0; } } void Modify(int l, int r, int pos, int x, int y, int z) { if (x <= l && r <= y) { node[pos].w = z * (r + 1 - l); node[pos].flag = z; return; } Push(l, r, pos); int m = l + r >> 1; if (x <= m) Modify(l, m, LSon(pos), x, y, z); if (y > m) Modify(m + 1, r, RSon(pos), x, y, z); Update(pos); } int Query(int l, int r, int pos, int x, int y) { if (x <= l && r <= y) return node[pos].w; Push(l, r, pos); 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, q; int x, y, z; SegTree tree; int main() { int tot_case; scanf("%d", &tot_case); for (int t = 0; t < tot_case; t++) { scanf("%d", &n); scanf("%d", &q); tree.Build(1, n, ROOT); for (int i = 0; i < q; ++i) { scanf("%d%d%d", &x, &y, &z); tree.Modify(1, n, ROOT, x, y, z); } printf("Case %d: The total value of the hook is %d.\n", t + 1, tree.Query(1, n, ROOT, 1, n)); } return 0; }