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;
}