zoukankan      html  css  js  c++  java
  • hihocoder 1080 线段树:区间加法&赋值

    1080 : 更为复杂的买卖房屋姿势
    http://hihocoder.com/problemset/problem/1080

    题面蛮好玩的,,也行是因为我玩模拟城市的缘故
    这里写图片描述

    修模板了

    带两个操作的话,注意set和tag的顺序
    每次down的时候先放set标记,再放tag标记
    每次更新set的时候要把tag清空

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N =260000;
    int n,m;
    struct linetree{
        #define lc  (t<<1)
        #define rc  (t<<1^1)
        #define mid (l[t]+r[t]>>1)
        int l[N],r[N],M,tag[N],sum[N],len[N],Set[N];
        inline void build(int n){
            M=1; while(M<n)M<<=1; M--;//get M
            memset(sum,0,sizeof(sum));
            memset(tag,0,sizeof(tag));
            memset(Set,0,sizeof(Set));
            for (int i=1+M;i<=M*2+1;i++){//leaf
                if(i<=n+M)scanf("%d",&sum[i]);
                l[i] = r[i] = i-M ;
                len[i]=1;
            }
            for (int t=M;t>=1;t--){//fathers
                sum[t]=sum[lc]+sum[rc];
                l[t]=l[lc], r[t]=r[rc];
                len[t]=len[lc]+len[rc];
            }
        }
        inline void down(int t){
            if (t>M){Set[t]=tag[t]=0;return ;}//leaf node
            if (Set[t]){
                sum[lc]=Set[t]*len[lc];
                sum[rc]=Set[t]*len[rc];
                Set[lc]=Set[t];
                Set[rc]=Set[t];
                Set[t] = 0;
                tag[lc]=tag[rc]=0;//!!!
            }
            if (tag[t]){
                sum[lc]+=tag[t]*len[lc];
                sum[rc]+=tag[t]*len[rc];
                tag[lc]+=tag[t];
                tag[rc]+=tag[t];
                tag[t] = 0;
            }
        }
        inline void _tag(int t,int x){
            sum[t]+=x*len[t];
            tag[t]+=x;
        }
        inline void _set(int t,int x){
            sum[t]=x*len[t];
            Set[t]=x;
            tag[t]=0;//!!!
        }
        void change(int t,int L,int R,int x){
            if (L<=l[t]&&r[t]<=R){_tag(t,x);return;}
            down(t);
            if (L<=mid)change(lc,L,R,x);
            if (mid< R)change(rc,L,R,x);
            sum[t]=sum[lc]+sum[rc];
        }
        void set(int t,int L,int R,int x){
            if (L<=l[t]&&r[t]<=R){_set(t,x);return;}//in
            down(t);
            if (L<=mid)set(lc,L,R,x);
            if (mid< R)set(rc,L,R,x);
            sum[t]=sum[lc]+sum[rc];
        }
        int query(int t,int L,int R){
            if (L<=l[t]&&r[t]<=R)return sum[t];
            down(t);
            int ans = 0;
            if (L<=mid)ans+=query(lc,L,R);
            if (mid< R)ans+=query(rc,L,R);
            return ans;
        }
    }T;
    
    int main(){
        //freopen("fuck.in","r",stdin);
        int ord,l,r,x;
        for (;~scanf("%d%d",&n,&m);){
            n++;
            T.build(n);
            for (;m--;){
                scanf("%d%d%d%d",&ord,&l,&r,&x);
                l++;r++;
                if (ord) T.set(1,l,r,x);
                else T.change(1,l,r,x);
                printf("%d
    ",T.sum[1]);
            }
        }
        return 0;
    }
    

    自己写的时候还是不够细心,down里面set直接复制的tag的
    然后+=忘了改成=,同时忘了清空tag标记

    以后写数据结构还是要细(la)心(ban)啊

  • 相关阅读:
    实战DeviceIoControl 之五:列举已安装的存储设备
    zend server 安装及相关配置
    php中echo 与print 的区别
    PHP:Deprecated: Function set_magic_quotes_runtime() is deprecated 错误
    php与ascii码
    计算EXCEL列名代号的程序
    笔记本电脑键盘不能正常输入字符
    读写注册表
    创建用于监视对student表进行插入和更新操作的触发器
    在客户机上安装Windows服务
  • 原文地址:https://www.cnblogs.com/cww97/p/7533977.html
Copyright © 2011-2022 走看看