[线段树 段更新] HDU

来源:互联网 发布:网络投资理财万盈金融 编辑:程序博客网 时间:2024/05/29 16:28
            **[线段树 段更新] HDU - 1698 E - Just a Hook**

题目大意:有一个长度为n的钩子,它由n个小钩子构成,每个小钩子初值为1。由一种操作,对于区间
[x,y],将该区间内每个小钩子的值更新为x(1<=x<=3)。求最后大钩子的总价值。
分析:刚开始做线段树,第一次写的时候我只是单纯更新相应区间,没有考虑当区间不是正好包含的时候,一直不对。第二次,我每次更新都更新到叶子,果断T。。。然后我就用了最入门的段更新的方法(一开始我想了想感觉没必要),看到别的博客说叫做懒惰标记。。。

#include <stdio.h>struct node{    int l,r;    int sum;    int lnc;//增量 };node tree[400005];int mid(int root){    return (tree[root].l+tree[root].r)/2;}void BuildTree(int root,int l,int r)//建树 初始化 {  tree[root].l=l;  tree[root].r=r;  tree[root].sum=r-l+1;  tree[root].lnc=0;  if(l!=r)  {    BuildTree(2*root+1,l,mid(root));    BuildTree(2*root+2,mid(root)+1,r);  } }void updata(int root,int a,int b,int v){    if(tree[root].l==a&&tree[root].r==b)//当前区间与操作区间完全重合,直接更新sum,打上标记     {        tree[root].sum=(b-a+1)*v;        tree[root].lnc=v;        return;    }    if(tree[root].lnc!=0)//不完全重合时,如果存在标记,左右更新标记     {     updata(2*root+1,tree[root].l,mid(root),tree[root].lnc);     updata(2*root+2,mid(root)+1,tree[root].r,tree[root].lnc);       tree[root].lnc=0;//消除标记     }    //判断区间情况 递归更新     if(b<=mid(root))    {      updata(2*root+1,a,b,v);    }    else if(a>mid(root))    {      updata(2*root+2,a,b,v);       }    else    {      updata(2*root+1,a,mid(root),v);      updata(2*root+2,mid(root)+1,b,v);     }    //函数回溯时,直接更新当前节点的sum     tree[root].sum=tree[2*root+1].sum+tree[2*root+2].sum;   }int main(int argc, char *argv[]){    int T;    scanf("%d",&T);    int ans=0;    while(T--)    {        int n;        scanf("%d",&n);        BuildTree(0,1,n);        int q;        scanf("%d",&q);        int x,y,z;        for(int i=0;i<q;i++)        {          scanf("%d %d %d",&x,&y,&z);          updata(0,x,y,z);        }        printf("Case %d: The total value of the hook is %d.\n",++ans,tree[0].sum);    }    return 0;}
原创粉丝点击