HDU 1698(线段树 区域更新,区域求值)

来源:互联网 发布:mac磁盘工具抹掉 失败 编辑:程序博客网 时间:2024/06/05 10:13

题目链接:点击打开链接

//区域更新 区域查询//需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候//PushDown()需要认真想明白;//大体意思是://每次查询到(L,R)大于(l,r)的区间,先把此段更新(或是替换原来的col),然后回溯,更新(PushUp)父节点们//不先去管子节点们,反正已经此段标记过了//当查询到的段不为 (L,R)大于(l,r)的区间,就要考虑当前段->是否之前更新的还未传给子节点(此段col不为零说明未传给子节点)//需要PushDown()一下(记得取消此段的col标记),让子节点成为之前应变成但未变成的样子,再去处理子节点#include <cstdio>#include <cstring>#include <iostream>using namespace std;#define MAXN 100005int setTree[MAXN<<2];int col[MAXN<<2];void PushUp(int root){setTree[root]=setTree[root<<1]+setTree[root<<1|1];}void PushDown(int root,int wideth){if(col[root]){col[root<<1]=col[root<<1|1]=col[root];setTree[root<<1]=col[root]*(wideth-(wideth>>1));setTree[root<<1|1]=col[root]*(wideth>>1);col[root]=0;}}void Build(int l,int r,int root){col[root]=0;if(l==r){setTree[root]=1;return;}int m=(l+r)>>1;Build(l,m,root<<1);Build(m+1,r,root<<1|1);PushUp(root);}void Update(int L,int R,int key,int l,int r,int root){//区域更新最关键也是最难理解的地方if(L<=l&&R>=r){setTree[root]=((r-l)+1)*key;col[root]=key;return;}PushDown(root,r-l+1);int m=(l+r)>>1;if(L<=m)   Update(L,R,key,l,m,root<<1);if(R>m)   Update(L,R,key,m+1,r,root<<1|1);PushUp(root);}int main(){int t,m,n;int x,y,z;cin>>t;for(int i=1;i<=t;i++){cin>>n>>m;Build(1,n,1);for(int j=1;j<=m;j++){scanf("%d%d%d",&x,&y,&z);Update(x,y,z,1,n,1);}printf("Case %d: The total value of the hook is %d.\n",i,setTree[1]);}return 0;}





1 0