zoukankan      html  css  js  c++  java
  • 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
    ",ans);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    springboot之手动控制事务
    Java的几种常见排序算法
    Java之协程(quasar)
    中文字符和中文标点符号的正则表达式
    【转】SignalR与ActiveMQ结合构建实时通信
    【转】根据Quartz-Cron表达式获取最近几次执行时间
    【转】IIS请求筛选模块被配置为拒绝超过请求内容长度的请求
    【转】C# 中Linq查询所有上级节点或所有下级节点
    【转】FluentAPI详细用法
    【转】SQL数据库日志文件收缩
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3831107.html
Copyright © 2011-2022 走看看