【线段树成段更新-模板】【HDU1698】Just a Hook

题意 Q个操作,将l,r 的值改为w

问最后1,n的sum 为多少


成段更新(通常这对初学者来说是一道坎),需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候

题意:O(-1)
思路:O(-1)
线段树功能:update:成段替换 (由于只query一次总区间,所以可以直接输出1结点的信息)


线段:1-N(题目天然给出)

区间和性质:求sum

重点在于如何设计一个lazy操作

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=100000+5;
int CASE;
using namespace std;
int N,Q;
int tree[maxn*4];
int col[maxn*4]; //延迟标记
void Pushup(int rt)                     //向上更新
{
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
int build(int l,int r,int rt)           //与以往差不多,注意延迟标记的重新赋值,有了build 一般不用memset初始化了
{
    col[rt]=0;
    if(l==r) {tree[rt]=1;return 0;}
    int m=(l+r)/2;
    build(lson);
    build(rson);
    Pushup(rt);
}
void Pushdown(int rt,int k)          //k是长度
{
    if(col[rt])
        {
            col[rt<<1]=col[rt<<1|1]=col[rt];
            tree[rt<<1]=(k-(k>>1))*col[rt];
            tree[rt<<1|1]=(k>>1)*col[rt];
            col[rt]=0;
        }
}
int update(int L,int R,int c,int l,int r,int rt) {
       if (L<=l&&r<= R) {
              col[rt]=c;               //不同题目处理方式不同,这里不属于下放操作,属于更新操作,与下放没有任何冲突关系
              tree[rt]=c*(r-l+1);
              return 0;
       }
       Pushdown(rt,r-l+1);             //Lazy 下放
       int m=(l+r)>>1;                  //下面与以往一样
       if (L<=m) update(L,R,c,lson);
       if (R>m) update(L,R,c,rson);
       Pushup(rt);
}
void solve()
{
    int  ll,rr,w;
    for(int i=1;i<=Q;i++)
    {
        scanf("%d%d%d",&ll,&rr,&w);
        update(ll,rr,w,1,N,1);
    }
    printf("Case %d: The total value of the hook is %d.\n",CASE,tree[1]);
}
int main()
{
	int T;
	cin>>T;
	CASE=0;
	while(T--)
    {
        CASE++;
        cin>>N>>Q;
        build(1,N,1);
        solve();
    }
    return 0;
}


posted on 2015-04-08 11:49  DDUPzy  阅读(250)  评论(0编辑  收藏  举报

导航