题目连接:
http://acm.hdu.edu.cn/showproblem.php?pid=1698
题目大意:
有一个钩子有n条棍子组成,棍子有铜银金三种组成,价值分别为1,2,3。为了对付每场战斗需要对组成钩子某个区间的棍子进行调整。问经过q次调整后钩子的总价值是多少?
解题思路:
线段树更新。因为数据范围的问题,每次更新到节点会TLE。用区间更新就会节省很多的时间,对每一个区间来讲,如果这个区间里面的棍子都是相同类型的,就用一个节点变量记录棍子类型,如果区间内棍子是不同类型,则将变量记录为-1。
1 //#include <bits/stdc++.h> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 const int manx = 400000; 8 struct node 9 { 10 int l, r, x; 11 int Mid() 12 { 13 return (l+r)/2; 14 } 15 } tree[manx]; 16 void build (int root, int l, int r) 17 {//建树,棍子都为铜质 18 tree[root].l = l; 19 tree[root].r = r; 20 tree[root].x = 1; 21 if (l == r) 22 return ; 23 build (2*root+1, l, tree[root].Mid()); 24 build (2*root+2, tree[root].Mid()+1, r); 25 } 26 void update (int root, int l, int r, int s) 27 { 28 if (tree[root].l==l && tree[root].r==r) 29 {//当前区间都为s类型的棍子 30 tree[root].x = s; 31 return ; 32 } 33 else if (tree[root].x != -1) 34 {//当前区间棍子并不一样,需要把当前区间的状态转移到左右子树并标记当前区间 35 tree[2*root+1].x = tree[2*root+2].x = tree[root].x; 36 tree[root].x = -1; 37 } 38 if (r <= tree[root].Mid()) 39 update (2*root+1, l, r, s); 40 else if (l > tree[root].Mid()) 41 update (2*root+2, l, r, s); 42 else 43 { 44 update (2*root+1, l, tree[root].Mid(), s); 45 update (2*root+2, tree[root].Mid()+1, r, s); 46 } 47 } 48 int Sum (int root, int l, int s) 49 { 50 if (tree[root].x != -1)//当前区间棍子类型一样,则不再向下查询 51 return tree[root].x * (s - l + 1); 52 else 53 { 54 return Sum(2*root+1, l, tree[root].Mid()) + Sum(2*root+2, tree[root].Mid()+1, s); 55 } 56 } 57 int main () 58 { 59 int t, l = 0; 60 scanf ("%d", &t); 61 while (t --) 62 { 63 int n, q; 64 scanf ("%d %d", &n, &q); 65 build (0, 1, n); 66 while (q --) 67 { 68 int a, b, x; 69 scanf ("%d %d %d", &a, &b, &x); 70 update (0, a, b, x); 71 } 72 int res = Sum(0, 1, n); 73 printf ("Case %d: The total value of the hook is %d. ", ++l, res); 74 } 75 return 0; 76 }