码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1698 ( 延迟标记,区间更新(赋值)求和 )

时间:2017-10-21 13:31:56      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:uil   oid   左右   std   范围   求和   cst   str   print   

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.\n" ,++Case , tree[1].sum  ) ; 
        
    }
    return 0 ; 
}
/*   题解链接(没看懂可以看看这个题解) 
http://blog.sina.com.cn/s/blog_87cb8e680100vek9.html*/ 

 

HDU 1698 ( 延迟标记,区间更新(赋值)求和 )

标签:uil   oid   左右   std   范围   求和   cst   str   print   

原文地址:http://www.cnblogs.com/yi-ye-zhi-qiu/p/7698795.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!