kuangbin专题七:E题 Just a Hook ( 延迟标记,区间更新(赋值)求和 )

HDU  1698  ( 延迟标记,区间更新(赋值)求和 )
Just a Hook
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=1698

////////////////////////////////////
注意  :  lazy思想的简单应用,所谓的lazy思想就是成段更新,用一个变量标记该段被更新过,
便把这个消息传给子树。lazy思想用通俗的话讲就是查找到该处,就更新,否则不要动。

题意 : 有一根长度  1 -- n  的钩子    刚开始钩子为 铜质 每单位长度价值为一
        输入  x , y , z ; 代表 x -- y 数段 的 钩子 的价值 被更改为  z
最后输出长为 n 的钩子的总价值  

#include<cstdio>
#include<algorithm>

using namespace std ; 


typedef struct ndoe{
    int l , r ; 
    int sum , flag ; 
}Lnode;

Lnode tree[2000000] ;

void build(int i , int l , int r){
    //  建立线段树 
    tree[i].l = l ;        // 初始化 树节点的   数段范围 
    tree[i].r = r ; 
    tree[i].flag = 0 ;     //  初始化 树节点的  标记 
    tree[i].sum = (l-r+1) ; // 初始化当前树节点 所代表的 和 
    if(l==r){     // 当左边等于右边     意味着当前节点是树的最后一个节点 
        return;    //    因为上边已经给节点赋值   所以此处不需要再赋值  
    }
    int mid = (l+r)/2 ; 
    build(2*i , l , mid) ;        //  建立左右 孩子 数段 
    build(2*i+1 , mid+1 , r) ; 
}

void update(int l , int r , int flag , int i){
    // 修改 区间 值                                                      } 
    if(r<tree[i].l||tree[i].r < l)                                //       } 递归 返回的条件 
        return;                                                   //       }   
    if(l<=tree[i].l && tree[i].r <=r){                            //       }
        tree[i].flag = flag ; //  延迟标记                        //       }    
        tree[i].sum = (tree[i].r - tree[i].l + 1) * tree[i].flag ; //      }
        return;                                                   //       }
    }                                                             //       }
    
    if(tree[i].flag){// 用到被标记的 数段 时  延迟标记向下传递         //  } 当 递归 进行到《《以前》》被标记 过得 
        int ll=2*i , rr = 2*i+1 ;//                                    //  }   数段时  首先 把 此数段 的标记 
        tree[ll].flag = tree[i].flag ;                                 //  } 向下 传递   然后计算  此 数段  
        tree[ll].sum = (tree[ll].r - tree[ll].l + 1) * tree[ll].flag ; //  } 左右两个字数段的值 
        tree[rr].flag = tree[i].flag  ;                                //  } 
        tree[rr].sum = ( tree[rr].r - tree[rr].l + 1) * tree[rr].flag ; // }
        tree[i].flag = 0;  
    }
    
    update(l , r , flag , 2*i) ;                                       // }  从父亲数段 向左右节点数段递归 查找要求中 
    update(l , r , flag , 2*i+1) ;                                    //  }  需要被标记的数段   并 用上面的代码 标记之 
                                                                      //  }  同时 结束递归返回 
    tree[i].sum = tree[2*i].sum + tree[2*i+1].sum ;        // 主数段将两个通过递归计算出结果的值相加求和 
}


int main(){
    int t , n  , m , x , y , z , Case = 0  ;
    scanf("%d" , &t) ; 
    while(t--){
        scanf("%d%d" , &n , &m ) ; 
        build(1 ,1 , n ) ; // 建立节电标号为 1 -> n 根节点为 1 的线段树 
        for(int i=1 ; i<=m  ; i++){
            scanf("%d%d%d" , &x , &y , &z) ; 
            update(x , y , z , 1 ) ; 
        }
        printf("Case %d: The total value of the hook is %d.
" ,++Case , tree[1].sum  ) ; 
        
    }
    return 0 ; 
}
/*   题解链接(没看懂可以看看这个题解) 
http://blog.sina.com.cn/s/blog_87cb8e680100vek9.html*/ 
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std ;

#define maxn 110000
int num[maxn] ;
int n , q ;
int a , b , c ;

struct node {
    int l ,
        r ,
        sum ,
        flag ;
};

node tree[maxn*4] ;

void build(int root , int l , int r) {

    tree[root].l = l ;
    tree[root].r = r ;
    tree[root].flag = 0 ;
    if(l == r ) {
        tree[root].sum = 1 ;
        return;
    }

    int mid = (l+r)/2 ;
    build(root*2 , l , mid ) ;
    build(root*2+1 , mid+1 , r ) ;

    tree[root].sum = tree[root*2].sum = tree[root*2+1].sum ;
}

void update(int root , int l , int r , int value ) {
    if(r < tree[root].l || tree[root].r < l) {
        return;
    }

    if(l <= tree[root].l && tree[root].r <= r) {
        tree[root].sum = (tree[root].r - tree[root].l + 1 ) * value ;
        tree[root].flag = value ;
        return;
    }

    if(tree[root].flag) {
        tree[root*2].flag = tree[root].flag ;
        tree[root*2].sum = (tree[root*2].r - tree[root*2].l + 1 ) * tree[root*2].flag ;

        tree[root*2+1].flag = tree[root].flag ;
        tree[root*2+1].sum = (tree[root*2+1].r - tree[root*2+1].l + 1 ) * tree[root*2+1].flag ;

        tree[root].flag = 0 ;
    }

    update(root*2 , l , r , value ) ;
    update(root*2+1 , l  ,r , value ) ;
    tree[root].sum = tree[root*2].sum + tree[root*2+1].sum ;
}

int main() {
    int t ;
    scanf("%d" , &t) ;
    for(int Case=1 ; Case<=t ; Case++) {

        scanf("%d" , &n) ;

        scanf("%d" , &q) ;
        build(1 , 1 , n ) ;
        for(int i=1;  i<=q ; i++) {
            scanf("%d %d %d" , &a , &b , &c) ;
            update(1 , a , b , c ) ;
        }

        printf("Case %d: The total value of the hook is %d.
" , Case, tree[1].sum) ;
    }
    return 0 ;
}
View Code
原文地址:https://www.cnblogs.com/yi-ye-zhi-qiu/p/7698795.html