Codeforces 444C 线段树 懒惰标记

前天晚上的CF比赛div2的E题,很明显一个线段树,当时还在犹豫复杂度的问题,因为他是区间修改和区间查询,肯定是要用到懒惰标记。

然后昨天真的是给这道题跪了,写了好久好久,。。。我本来是写了个add标记作为累加用,因为这个题目很明显是累加型的懒惰标记,但是后来不知道脑子怎么想的,又把add标记给删了,认为只要用一个set标记标注此时该树是否是连续相同的,如果是,则值就存在setv【rt】中,然后就开始了漫长的WA的过程,很明显,我这样是采用了覆盖性的懒惰标记,每次我pushdonw下去 还要先pushdonw下一层的,。。。如果真这么写 绝壁TL,不这么写 肯定WA,。。明显一个累加型的懒惰标记,硬是给我写跪了,其实我后来意识到了要用累加型的,可是就是想沿着这个思路 改好。。最后躺在床上一想,真的只能用累加型的懒惰标记

发现线段树的懒惰标记这一块真的还不熟练,各种容易出错。。。赶紧练

#include <iostream>
#include <cstdio>
#include <cstring>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define LL __int64
using namespace std;
const int N=100000+20;
LL d[N<<2],cur[N<<2],flag[N<<2],add[N<<2];
int n,m;
LL abs(LL x){
    if (x<0) return -x;
    return x;
}
void build(int rt,int l,int r)
{
    d[rt]=cur[rt]=flag[rt]=add[rt]=0;
    if (l>=r){
        cur[rt]=l;
        flag[rt]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
}
void up(int rt,int l,int r)
{
    d[rt]=d[rt<<1]+d[rt<<1|1];
    if (flag[rt<<1] && flag[rt<<1|1] && cur[rt<<1]==cur[rt<<1|1]){
            cur[rt]=cur[rt<<1];
            flag[rt]=1;
    }
    else{
        flag[rt]=0;
    }
}
void pushdown(int rt,int l,int r)
{
    if (l>=r) return;
    int mid=(l+r)>>1;
    if (add[rt]>0){
        d[rt<<1]+=add[rt]*(mid-l+1);
        d[rt<<1|1]+=add[rt]*(r-mid);
        add[rt<<1]+=add[rt];
        add[rt<<1|1]+=add[rt];
        add[rt]=0;
    }
    if (flag[rt]>0){
        cur[rt<<1]=cur[rt<<1|1]=cur[rt];
        flag[rt<<1]=flag[rt<<1|1]=1;
    }
}
void fix(int L,int R,LL v,int rt,int l,int r)
{
    int mid=(l+r)>>1;
    if (L<=l && r<=R){
        if (flag[rt]>0){
            d[rt]+=abs(v-cur[rt])*(r-l+1);
            add[rt]+=abs(v-cur[rt]);
            cur[rt]=v;
            return;
        }
    }
    pushdown(rt,l,r);
    if (L<=mid) fix(L,R,v,lson);
    if (R>mid)  fix(L,R,v,rson);
    up(rt,l,r);

}
LL query(int L,int R,int rt,int l,int r)
{
    //pushdown(rt,l,r);
    if (L<=l && r<=R) return d[rt];
    int mid=(l+r)>>1;
    pushdown(rt,l,r);
    LL ret1,ret2;
    ret1=ret2=0;
    if (L<=mid) ret1=query(L,R,lson);
    if (R>mid)  ret2=query(L,R,rson);
    return ret1+ret2;
}
int main()
{
    int op,a,b;
    LL c;
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,1,n);
        while (m--)
        {
            scanf("%d",&op);
            if (op==1){
                scanf("%d%d%I64d",&a,&b,&c);
                fix(a,b,c,1,1,n);
            }
            else{
                scanf("%d%d",&a,&b);
                LL ans=query(a,b,1,1,n);
                printf("%I64d\n",ans);
            }
        }
    }
    return 0;
}

 

posted @ 2014-07-08 11:13  KRisen  阅读(540)  评论(0编辑  收藏  举报