题目链接:http://hdu.hustoj.com/showproblem.php?pid=1698
题意:没啥好说的,读题吧(;¬_¬)
思路:典型的线段树区间更新
代码:
1 #include<iostream> 2 using namespace std; 3 4 const int maxn = 1e5 + 10; 5 struct segTree 6 { 7 int left, right; 8 int val; 9 int addMark; //延迟标记 10 } segTree[maxn * 4]; 11 12 void pushUp(int rt) //更新父节点值 13 { 14 segTree[rt].val = segTree[rt * 2].val + segTree[rt * 2 + 1].val; 15 } 16 void build(int l, int r, int rt) 17 { 18 segTree[rt].addMark = 0; 19 segTree[rt].left = l; 20 segTree[rt].right = r; 21 segTree[rt].val = 1; //刚开始都是铜棒1 22 if(l == r) 23 { 24 return; 25 } 26 int mid = (l + r) / 2; 27 build(l, mid, rt * 2); 28 build(mid + 1, r, rt * 2 + 1); 29 pushUp(rt); 30 } 31 32 void pushDown(int rt) //更新延迟标记 33 { 34 if(segTree[rt].addMark != 0) //被标记了 35 { 36 //延迟标记传递更新 37 segTree[rt * 2].addMark = segTree[rt].addMark; //因为这里是直接改变,只记录最后结果,所以不用+=。eg:铜变银再变金,只记录金即可 38 segTree[rt * 2 + 1].addMark = segTree[rt].addMark; 39 //节点值传递更新 40 segTree[rt * 2].val = segTree[rt].addMark * (segTree[rt * 2].right - segTree[rt * 2].left + 1); 41 segTree[rt * 2 + 1].val = segTree[rt].addMark * (segTree[rt * 2 + 1].right - segTree[rt * 2 + 1].left + 1); 42 segTree[rt].addMark = 0; //标记清空 43 } 44 } 45 46 void update(int x, int y, int w, int l, int r, int rt) 47 { 48 if(x > r || y < l) 49 { 50 return; 51 } 52 if(x <= l && y >= r) 53 { 54 segTree[rt].addMark = w ; 55 segTree[rt].val = w * (segTree[rt].right - segTree[rt].left + 1) ; 56 return; 57 } 58 pushDown(rt); 59 int mid = (l + r) / 2; 60 if(x <= mid) 61 update(x, y, w, l, mid, rt * 2); 62 if(y > mid) 63 update(x, y, w, mid + 1, r, rt * 2 + 1); 64 pushUp(rt); 65 } 66 67 int main() 68 { 69 ios::sync_with_stdio(false); 70 int t, n, q, x, y, w, ca = 1; 71 cin >> t; 72 while(t--) 73 { 74 cin >> n >> q; 75 build(1, n, 1); 76 while(q--) 77 { 78 cin >> x >> y >> w; 79 update(x, y, w, 1, n, 1); 80 } 81 cout << "Case " << ca << ": The total value of the hook is " << segTree[1].val << "." << endl; 82 ca++; 83 } 84 return 0; 85 }
体会:
熟悉一下线段树区间更新操作的写法