题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698
题目大意:给你一些牌子(铜,银,金)分别用1,2,3表示,一开始这些都是铜牌。现在对这些区间区间进行操作,比如说将1到5的牌子涂成银牌等等。最后统计这些牌子的总价值。
思路:线段树解决,但是单点更新的线段树每次都会更新至叶子节点,而在本题中是不需要每次都更新到叶子节点的,因为最后只查询跟节点。所以可以每次查询到一个没更新的节点时更新他。这样就需要使用一个辅助的空间来标记每个节点的更新状态。
下面的代码是HH大牛的代码,膜拜
#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 111111;
int h , w , n;
int col[maxn<<2];
int sum[maxn<<2];
void PushUp(int rt) {
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int m) {
if (col[rt]) {
col[rt<<1] = col[rt<<1|1] = col[rt];
sum[rt<<1] = (m - (m >> 1)) * col[rt];
sum[rt<<1|1] = (m >> 1) * col[rt];
col[rt] = 0;
}
}
void build(int l,int r,int rt) {
col[rt] = 0;
sum[rt] = 1;
if (l == r) return ;
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt) {
if (L <= l && r <= R) {
col[rt] = c;
sum[rt] = c * (r - l + 1);
return ;
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
if (L <= m) update(L , R , c , lson);
if (R > m) update(L , R , c , rson);
PushUp(rt);
}
int main() {
// freopen("in","r",stdin);
int T , n , m;
scanf("%d",&T);
for (int cas = 1 ; cas <= T ; cas ++) {
scanf("%d%d",&n,&m);
build(1 , n , 1);
while (m --) {
int a , b , c;
scanf("%d%d%d",&a,&b,&c);
update(a , b , c , 1 , n , 1);
}
printf("Case %d: The total value of the hook is %d.\n",cas , sum[1]);
}
return 0;
}