HDU.1698 屠夫(线段树成段更新大大大水题)
题目大意:T组测试,每组n个钩子,起初每个钩子价值为1,然后m组更新,每次把[a,b]区域内的钩子的每个价值都更新为c。
然后让你求所有钩子价值的总和。
单点更新做了几道了,感觉想法越来越神,于是先换换口味。第一次写成段更新的题,看着两种风格的模版以及自己的习惯改来改去,虽然花了不少时间。但改的过程中也对懒惰标记加深了体会,看来多动脑更得勤动手。
存个自己的代码习惯
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; #define LL(x) (x << 1) #define RR(x) (x << 1 | 1) #define MID(x, y) (x + ((y - x) >> 1)) #define lson l, mid, LL(t) #define rson mid + 1, r, RR(t) #define MAX 100005 int n, m, t; class segment_tree { public: int tree[MAX * 4]; int col[MAX * 4]; int point[MAX * 4];//记录该节点下方左右子节点各有多少个节点 void build(int l, int r, int t) { tree[t] = r - l + 1; col[t] = 1; if(l == r) { point[t] = 1; } else { int mid = MID(l, r); build(lson); build(rson); point[t] = point[LL(t)] + point[RR(t)]; } } void PushUp(int t) { tree[t] = tree[LL(t)] + tree[RR(t)]; } void PushDown(int t) { if(col[t]) { col[LL(t)] = col[RR(t)] = col[t]; tree[LL(t)] = point[LL(t)] * col[LL(t)]; tree[RR(t)] = point[RR(t)] * col[RR(t)]; col[t] = 0; } } void update(int st, int ed, int l, int r, int t, int w) { if(st <= l && r <= ed) { col[t] = w; tree[t] = (r - l + 1) * col[t]; return ; } PushDown(t); int mid = MID(l, r); if(st <= mid) update(st, ed, lson, w); if(ed > mid) update(st, ed, rson, w); PushUp(t); } } seg; int main() { while(~scanf("%d", &t)) { int t_cnt = 0; while(t--) { scanf("%d%d", &n, &m); seg.build(1, n, 1); while(m--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); seg.update(a, b, 1, n, 1, c); } printf("Case %d: The total value of the hook is %d.\n",++t_cnt,seg.tree[1]); } } return 0; }