HDU 1698 Just a Hook(线段树的区间更新《标记》)

题目大意:首先区间1-N的数都是1,然后让你把区间a-b的值改变为c;

思路:裸的区间更新。比单点更新就是多了一个标记的la[]数组,用来代表在某个区间的数需要给便成la[],

其具体的用法就是,在创建线段树的同时要la[]数组清空。在区间改变时将改变的量赋值给la[],然后把la[]数组下放

对于此题,是将所有la[]的左右孩子都直接改变为la[]的值即可。然后改变左右孩子的sum[],有两种情况:左孩子和

sum[rt<<1]=la[rt]*(len-(len/2)),右孩子和sum[rt<<1|1]=la[rt]*(m/2);即当前的改变量la[]×区间的长度。最后要将当前节点的la[]标记消掉。(PS:线段数的数组大小在至少开原叶子点数的4倍,因为线段树其实就是一个完全的二叉树)。


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<math.h>
#define LL long long
#define inf 0x3f3f3f3f
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define M 1000100
using namespace std;
int sum[M*4],n,la[M*4];
void up(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void bu(int l,int r,int rt)
{
    la[rt]=0;
    if(l==r)
    {
        sum[rt]=1;
        return ;
    }
    int mid=(l+r)>>1;
    bu(ls);
    bu(rs);
    up(rt);
}
void down(int rt,int m)
{
    if(la[rt])
    {
        la[rt<<1]=la[rt<<1|1]=la[rt];
        sum[rt<<1]=la[rt]*(m-(m>>1) );
        sum[rt<<1|1]=la[rt]*(m>>1);
        la[rt]=0;
    }
}
void ch(int a,int b,int c,int l,int r,int rt)
{
    if(l>=a&&r<=b)
    {
        la[rt]=c;
        sum[rt]=c*(r-l+1);
        return ;
    }
    down(rt,r-l+1);
    int mid=(l+r)>>1;
    if(a<=mid)
        ch(a,b,c,ls);
    if(mid<b)
        ch(a,b,c,rs);
    up(rt);
}
int main()
{
    int m,i,j,k,cla,a,b,c;
    scanf("%d",&cla);
    for(int gr=1;gr<=cla;gr++)
    {
        scanf("%d",&n);
        bu(1,n,1);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            ch(a,b,c,1,n,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",gr,sum[1]);
    }
    return 0;
}






你可能感兴趣的:(线段树)