题目链接:[HDU 1698]Just a Hook[线段树区间更新]
题意分析:
屠夫的钩子被分割成n个节,每节初始时都有铜制,铜制每节价值为1.然后给出q个操作,改变段l,r的材料为其它材料。最终询问:此时钩子的总价值是多少?
解题思路:
线段树的区间更新。使用到了lazy思想,也就是代码中的add数组。
整个原理就是,更新的时候,当某段被包含在被更新区间内时,只需给该段标记一下改变量add就行了,然后直接返回。
只有当进行到更深层次的查询时,才将改变量向子区间传递。降低了更新的复杂度。
个人感受:
= =。屠夫boy这题放了好久了,一直想把lazy怎么弄的搞懂,结果其实结合着代码理解风味更佳:)
具体代码如下:
#include<iostream> #include<cstdio> #define lowbit(x) (x & (-x)) #define root 1, n, 1 #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 using namespace std; const int MAXN = 1e5 + 111; int sum[MAXN << 2], add[MAXN << 2]; void push_up(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void push_down(int rt, int x) { if (add[rt]) { sum[rt << 1] = (x - (x >> 1)) * add[rt]; sum[rt << 1 | 1] = (x >> 1) * add[rt]; add[rt << 1] = add[rt << 1 | 1] = add[rt]; add[rt] = 0; } } void build(int l, int r, int rt) { add[rt] = 0; if (l == r) { sum[rt] = 1; return; } int m = (l + r) >> 1; build(lson); build(rson); push_up(rt); } int query(int L, int R, int l, int r, int rt) { int ret = 0; if (L <= l && r <= R) { return sum[rt]; } int m = (l + r) >> 1; if (L <= m) ret += query(L, R, lson); if (m < R) ret += query(L, R, rson); return ret; } void update(int L, int R, int val, int l, int r, int rt) { if (L <= l && r <= R) { add[rt] = val; sum[rt] = val * (r - l + 1); return; } push_down(rt, r - l + 1); int m = (l + r) >> 1; if (L <= m) update(L, R, val, lson); if (m < R) update(L, R, val, rson); push_up(rt); } int main() { int t, n, q; for (int kase = scanf("%d", &t); kase <= t; ++kase) { scanf("%d", &n); build(root); scanf("%d", &q); int l, r, v; while (q --) { scanf("%d%d%d", &l, &r, &v); update(l, r, v, root); } printf("Case %d: The total value of the hook is %d.\n", kase, sum[1]); } return 0; }