http://acm.hdu.edu.cn/showproblem.php?pid=1698
线段树问题区间更新问题,使用到懒惰思想来降低时间复杂度。
题意:将一段区间上的权值修改为新的值后求和。
懒惰思想:
【1,10】
【1,5】 【6,10】
【1,3】 【4,5】 【6,8】 【9,10】
【1,2】 【3,3】 【4,4】 【5,5】 【6,7】 【8,8】 【9,9】 【10,10】
【1,1】【2,2】 【6,6】【7,7】
现在模拟一下lazy思想在样例中的应用。
第一步:将区间[1,5]上的值更新为2.
找到此区间并将这个区间的lazy赋值为2。
第二步:将区间[5,9]上的值更新为3.
我们先搜索到【1,10】发现【5,9】分为【5,5】,【6,9】分左右继续搜索,。
然后搜索到【1,5】它的lazy是2,由于没有搜索到【5,5】这个需要更新的区间,所以我们向下传递lazy标志【1,5】lazy变成0。
【1,3】,【4,5】由于lazy的传递lazy值更新为2,仍然没有搜索到【5,5】,所以继续向下传递lazy标志。
【1,2】,【3,3】lazy变成2,【4,4】也变成2,注意到我们搜索到了【5,5】它的lazy不是原来的2,而是3。
总的来说,就是有更新操作,我们先记录一下,而并不操作,最后询问的时候一并操作,降低时间复杂度。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 100000;
struct node{
int l,r,lazy;
int mid(){
return (l + r) >> 1;
}
}tree[MAX * 4];
void BTree(int l, int r, int rt){
tree[rt].l = l;
tree[rt].r = r;
tree[rt].lazy = 0;
if(l == r){
tree[rt].lazy = 1;
return;
}
int mid = tree[rt].mid();
BTree(l, mid, rt << 1);
BTree(mid + 1, r, rt << 1 | 1);
}//建树
void pushdown(int rt){
if(tree[rt].lazy){
tree[rt << 1].lazy = tree[rt << 1 | 1].lazy = tree[rt].lazy;
tree[rt].lazy = 0;
}
}//懒惰操作,符合条件向下传递懒惰标志.
void Update(int l, int r, int x, int rt){
if(tree[rt].l == l && tree[rt].r == r){
tree[rt].lazy = x;
return;
}
pushdown(rt);//如果没有找到更新的区间,就向下传递原来的懒惰标志.
int mid = tree[rt].mid();
if(r <= mid)
Update(l, r, x, rt << 1);
else if(l > mid)
Update(l, r, x, rt << 1 | 1);
else{
Update(l, mid, x, rt << 1);
Update(mid + 1, r, x, rt << 1 | 1);
}
}
int query(int rt, int id){
if(tree[rt].l == tree[rt].r){
return tree[rt].lazy;
}
pushdown(rt);//如果不是叶子节点,就将更新好的懒惰标志向下传递到叶子节点.
int mid = tree[rt].mid();
if(id <= mid) return query(rt << 1, id);
return query(rt << 1 | 1, id);
}
int main(){
// freopen("in.txt", "r", stdin);
int cas,t = 0;
scanf("%d",&cas);
while(cas--){
int n;
scanf("%d",&n);
BTree(1, n, 1);
int m;
scanf("%d",&m);
int l,r,x;
while(m--){
scanf("%d%d%d",&l,&r,&x);
Update(l, r, x, 1);
}
int ans = 0;
for(int i=1; i<=n; i++){
ans += query(1, i);
}
printf("Case %d: The total value of the hook is %d.\n",++t, ans);
}
return 0;
}