HDU 1698 【线段树,区间修改 + 维护区间和】
Problem Description:
In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same length.
Now Pudge wants to do some operations on the hook.
Let us number the consecutive metallic sticks of the hook from 1 to N. For each operation, Pudge can change the consecutive metallic sticks, numbered from X to Y, into cupreous sticks, silver sticks or golden sticks.
The total value of the hook is calculated as the sum of values of N metallic sticks. More precisely, the value for each kind of stick is calculated as follows:
For each cupreous stick, the value is 1.
For each silver stick, the value is 2.
For each golden stick, the value is 3.
Pudge wants to know the total value of the hook after performing the operations.
You may consider the original hook is made up of cupreous sticks.
Input:
The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 10 cases.
For each case, the first line contains an integer N, 1<=N<=100,000, which is the number of the sticks of Pudge’s meat hook and the second line contains an integer Q, 0<=Q<=100,000, which is the number of the operations.
Next Q lines, each line contains three integers X, Y, 1<=X<=Y<=N, Z, 1<=Z<=3, which defines an operation: change the sticks numbered from X to Y into the metal kind Z, where Z=1 represents the cupreous kind, Z=2 represents the silver kind and Z=3 represents the golden kind.
output:
For each case, print a number in a line representing the total value of the hook after the operations. Use the format in the example.
Sample Input:
1
10
2
1 5 2
5 9 3
Sample Output:
Case 1: The total value of the hook is 24.
大概题意:
一条长度为N得链子, 有Q次操作,每次操作把区间 X~Y 的金属换成 Z;有金,银,铜三种金属分别对应3,2,1三种价值。
求Q次操作后,求整条链子的总价值。
思路:
成段更新,区间求和,本次用一维数组表示法建线段树
AC code:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #define INF 0x3f3f3f3f 6 #define lson l, m, k<<1 ///左儿子 7 #define rson m+1, r, k<<1|1 ///右儿子 8 using namespace std; 9 10 const int MAXN = 100005; 11 12 int st[MAXN<<2]; ///st数组里面记录的是标记 0,1, 2, 3; 0 代表杂色 13 int flag; 14 15 void down(int &k) 16 { 17 st[k<<1] = st[k<<1|1] = st[k]; ///左儿子和右儿子均设为该颜色 18 st[k] = 0; ///设为杂色 ??避免后面重复操作?? 19 } 20 21 void build(int l, int r, int k) ///建立线段树,一开始都初始化为 1 22 { 23 st[k] = flag; 24 if(l == r) return; 25 int m = (l+r)>>1; 26 build(lson); 27 build(rson); 28 } 29 30 void update(int &L, int &R, int l, int r, int k) ///更新L--R,要从1--N, st[1] 开始 31 { 32 if(L <= l && R >= r) ///所在区间在更新区间内 33 { 34 st[k] = flag; ///整段更新为新颜色 35 return; 36 } 37 if(st[k]) ///如果该结点为纯色,则左右儿子颜色也为该颜色 38 { 39 down(k); 40 } 41 int m = (l+r)>>1; 42 if(L <= m) update(L, R, lson); 43 if(R > m) update(L, R, rson); 44 } 45 46 int query(int l, int r, int k) ///查询区间颜色之和 47 { 48 if(st[k]) return st[k]*(r-l+1); ///如果该段为纯色,则成段想乘得结果 49 50 int m = (l+r)>>1, t1, t2; 51 t1 = query(lson); 52 t2 = query(rson); 53 return t1+t2; 54 } 55 56 int main() 57 { 58 int T, N, t = 1; 59 int L, R, q; 60 scanf("%d", &T); 61 while(T--) 62 { 63 scanf("%d%d", &N, &q); 64 flag = 1; 65 build(1, N, 1); ///建立线段树 66 while(q--) 67 { 68 scanf("%d%d%d", &L, &R, &flag); 69 update(L, R, 1, N, 1); 70 } 71 printf("Case %d: The total value of the hook is %d.\n", t++, query(1, N, 1)); 72 } 73 return 0; 74 }