http://acm.hdu.edu.cn/showproblem.php?pid=1698
/*
本题题意
给定 t 组测试用例, 每组测试用例给定长度为n
的分数, 每个分数的初始值为1, 给定m组查询方法
查询方法 包括更新一个区间的分数为 1(铜钩子的分数), 或者 2(银钩子的分数) 或者 3(金钩子的分数), 最后需要输出整个
区间的值
本题思路:
此题需要更新整段区间的值, 查询,更新区间的值, 可以使用线段树
可以在单点更新线段树外套一个for循环, 但是这样时间复杂度很高会
到o(n2) 因此需要添加懒惰标记, 当遍历的树结点的左右子树对应的数组区间
不在查询时或更新条件的区间范围 l , r时就需要下放懒惰标记.
*/
#include<bits/stdc++.h>
using namespace std;
const int maxsize = 100005;
struct Node {
int l, r, sum, lazy;
update(int data) {
sum = (r - l + 1) * data; // 本题是更新到 不是在原基础上增加
lazy = data; // 本题是更新到 不是在原基础上增加
}
}tree[maxsize * 4];
int hook[maxsize];
void push_up(int x) {
tree[x].sum = tree[x<<1].sum + tree[x<<1|1].sum;
}
void push_down(int x) { // 下方懒惰标记的值
if(tree[x].lazy != 0) {
tree[x<<1].update(tree[x].lazy);
tree[x<<1|1].update(tree[x].lazy);
tree[x].lazy = 0;
}
}
void build(int x, int l, int r) { // 建树
tree[x].l = l, tree[x].r = r;
tree[x].sum = tree[x].lazy = 0;
if(l == r) {
tree[x].sum = hook[l];
} else {
int mid = (l + r) / 2;
build(x<<1, l , mid);
build(x<<1|1, mid + 1, r);
push_up(x);
}
}
void update(int x, int l, int r, int data) { // 更新树的结点
int L = tree[x].l, R = tree[x].r;
if(L >= l && R <= r) {
tree[x].update(data);
} else {
push_down(x);
int mid = (L + R) / 2;
if(mid >= l) update(x<<1, l, r, data);
if(mid < r) update(x<<1|1, l, r, data);
push_up(x);
}
}
int query(int x, int l, int r) { // 查找树的结点
int L = tree[x].l, R = tree[x].r;
if(L >= l && R <= r) {
return tree[x].sum;
} else {
push_down(x);
int mid = (L + R) / 2, res = 0;
if(mid >= l) res += query(x<<1, l, r);
if(mid < r) res += query(x<<1|1, l, r);
return res;
}
}
int main() {
int t, n, m, cnt = 1;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
hook[i] = 1;
}
int l, r, data;
build(1, 1, n);
for(int i = 0; i < m ;i++) {
scanf("%d%d%d", &l, &r, &data);
update(1, l, r, data);
}
//int ans = tree[1].sum;
int ans = query(1, 1, n);
printf("Case %d: The total value of the hook is %d.\n", cnt++, ans);
}
return 0;
}