1. 程式人生 > >hdu1698 Just a Hook(線段樹,區間更新)

hdu1698 Just a Hook(線段樹,區間更新)

題目連結:http://acm.split.hdu.edu.cn/showproblem.php?pid=1698

題意:

某個鉤子由n個小鉤子組成,有q個操作,將某個區間內的小鉤子的材料改變,有金銀銅三中材料,每種材料價錢不同。問最後這個鉤子的價值

注意,題目中預設初始化時,n個小鉤子全為銅

思路:

線段樹,區間更新(不是相加更新),最後輸出根節點的值即可。關鍵在於,如何理出用線段樹來解決這一題,重點是理解更新。

程式碼:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
const int maxn = 100000;

int sum[4*maxn+5];
int add[4*maxn+5];

void up(int rt){
	sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

void down(int rt, int len){
	if(add[rt]){
		add[rt<<1] = add[rt];
		add[rt<<1|1] = add[rt];
		sum[rt<<1] = add[rt] * (len-(len>>1));
		sum[rt<<1|1] =  add[rt] * (len>>1);
		add[rt] = 0;
	}
}

void build(int rt, int l, int r){
	if(l==r){
		sum[rt] = 1;
	}
	else{
		int mid = (l+r)>>1;
		build(rt<<1, l, mid);
		build(rt<<1|1, mid+1, r);
		up(rt);
	}
	return;
}

void update(int rt, int val, int x, int y, int l, int r){
	if(x<=l && r<=y){
		sum[rt] = val*(r-l+1);
		add[rt] = val;
	}
	else{
		down(rt, r-l+1);
		int mid = (l+r)>>1;
		if(x<=mid) update(rt<<1, val, x, y, l, mid);
		if(y>mid) update(rt<<1|1, val, x, y, mid+1, r);
		up(rt);
	}
}


int main(){
	int t, n, q, x, y, z, cnt=0;
	scanf("%d", &t);
	while(t--){
		memset(sum, 0, sizeof(sum));
		memset(add, 0, sizeof(add));

		scanf("%d%d", &n, &q);

		build(1, 1, n);
		for(int i=0; i<q; i++){
			scanf("%d%d%d", &x, &y, &z);
			update(1, z, x, y, 1, n);
		}

		printf("Case %d: The total value of the hook is %d.\n", ++cnt, sum[1]);
	}
	return 0;
}