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.\n" ,++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.\n" , Case, tree[1].sum) ; } return 0 ; }