HDU1698【屠夫的钩子】

具体细节在代码里面,算是一个区间修改,点查询吧。

成段更新(通常这对初学者来说是一道坎),

需要用到延迟标记(或者说懒惰标记),

简单来说就是每次更新的时候不要更新到底,

用延迟标记使得更新延迟到下次需要更新or询问到的时候


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r

const int maxn=100005;
int n;

int sum[maxn<<3];
int col[maxn<<3];

void Pushup(int rt)
{
  sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void Pushdown(int rt,int m)
{
    if(col[rt])
    {
        col[rt<<1]=col[rt<<1|1]=col[rt];
        sum[rt<<1]=(m-(m>>1))*col[rt];
        sum[rt<<1|1]=(m>>1)*col[rt];
        col[rt]=0;//大注意2. 一定得记得改回来。
    }
}
void build(int rt,int l,int r)
{
    sum[rt]=1;
    if(l==r) return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    Pushup(rt);
}
void update(int ql,int qr,int ch,int rt,int l,int r)
{
    if(ql<=l&&qr>=r)
    {
        col[rt]=ch;
        sum[rt]=ch*(r-l+1);
        return;
    }
    Pushdown(rt,r-l+1);//会执行这一步的前提是要修改的已经插入已经标记未传给子结点的

    int m=(l+r)>>1;
    if(ql<=m)
       update(ql,qr,ch,lson);
    if(qr>m)
        update(ql,qr,ch,rson);
    Pushup(rt);
}

int main()
{
    int case_num,qnum,a,b,c;
    scanf("%d",&case_num);
    for(int i=1;i<=case_num;i++)
    {
        //注意1.每次还真得memset,或在build里面加入 col[i]=0;
        memset(col,0,sizeof(col));
        scanf("%d",&n);
        build(1,1,n);

        //printf("%d
",sum[1]);

        scanf("%d",&qnum);
        while(qnum--)
        {
            scanf("%d%d%d",&a,&b,&c);
            update(a,b,c,1,1,n);
            //printf("~%d %d %d %d
",sum[1],col[1],col[2],col[3]);
        }
        printf("Case %d: The total value of the hook is %d.
",i,sum[1]);
    }
    return 0;
}


原文地址:https://www.cnblogs.com/bbsno1/p/3279798.html