zoukankan      html  css  js  c++  java
  • NotOnlySuccess大神的飘逸版线段树

    吐槽:在模板题,我的丑陋的线段树跑了984ms,而大神的只跑了364ms,看来我的代码还是太丑了QAQ


    大神的线段树也没什么大优化,就是不知道为什么超级快,或许是我以前看的线段树代码不好吧。。。
    我推荐这个线段树的主要原因就是非常好写,空间也是非常小,思路极其清晰。
    好了,废话不多说,直接上代码:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=100001;
    ll sum[maxn<<2];
    ll add[maxn<<2];
    inline void pushup(int rt){
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void build(int l,int r,int rt){
        if(l==r){
            scanf("%lld",&sum[rt]);
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        pushup(rt);
    }
    inline void pushdown(int rt,int len){
        if(add[rt]){
            add[rt<<1]+=add[rt];
            add[rt<<1|1]+=add[rt];
            sum[rt<<1]+=add[rt]*(len-(len>>1));
            sum[rt<<1|1]+=add[rt]*(len>>1);
            add[rt]=0;
        }
    }
    void update(int L,int R,int c,int l,int r,int rt){
        if(L<=l&&r<=R){
            add[rt]+=c;
            sum[rt]+=c*(r-l+1);
            return;
        }
        pushdown(rt,r-l+1);
        int mid=(l+r)>>1;
        if(L<=mid)update(L,R,c,l,mid,rt<<1);
        if(mid+1<=R)update(L,R,c,mid+1,r,rt<<1|1);
        pushup(rt);
    }
    ll query(int L,int R,int l,int r,int rt){
        if(L<=l&&r<=R){
            return sum[rt];
        }
        pushdown(rt,r-l+1);
        ll ans=0;
        int mid=(l+r)>>1;
        if(L<=mid)ans+=query(L,R,l,mid,rt<<1);
        if(mid+1<=R)ans+=query(L,R,mid+1,r,rt<<1|1);
        return ans;
    }
    int main(){
        int n,m;
        scanf("%d %d",&n,&m);
        build(1,n,1);
        for(int i=1;i<=m;i++){
            int g;
            scanf("%d",&g);
            if(g&1){
                int l,r;
                ll c;
                scanf("%d %d %lld",&l,&r,&c);
                update(l,r,c,1,n,1);
            }
            else{
                int l,r;
                scanf("%d %d",&l,&r);
                printf("%lld
    ",query(l,r,1,n,1));
            }
        }
        return 0;
    }

    以上是区间加+区间和
    下面是区间加+区间乘+区间和:(这代码好难调啊)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=100001;
    ll p;
    ll sum[maxn<<2];
    ll add[maxn<<2];
    ll mul[maxn<<2];
    inline void pushup(int rt){
        sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
    }
    inline void mark(int l,int r,int rt,ll a,ll b){
        sum[rt]=(sum[rt]*a+(r-l+1)*b)%p;
        mul[rt]=(mul[rt]*a)%p;
        add[rt]=(add[rt]*a+b)%p;
    }
    inline void pushdown(int l,int r,int rt){
        if(mul[rt]!=1||add[rt]!=0){
            int mid=(l+r)>>1;
            mark(l,mid,rt<<1,mul[rt],add[rt]);
            mark(mid+1,r,rt<<1|1,mul[rt],add[rt]);
            add[rt]=0;
            mul[rt]=1;
        }
    }
    void build(int l,int r,int rt){
        mul[rt]=1;
        if(l==r){
            scanf("%lld",&sum[rt]);
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        pushup(rt);
    }
    void update(int L,int R,int l,int r,int rt,ll a,ll b){
        if(L<=l&&r<=R){
            mark(l,r,rt,a,b);
            return;
        }
        pushdown(l,r,rt);
        int mid=(l+r)>>1;
        if(L<=mid)update(L,R,l,mid,rt<<1,a,b);
        if(mid+1<=R)update(L,R,mid+1,r,rt<<1|1,a,b);
        pushup(rt);
    }
    ll query(int L,int R,int l,int r,int rt){
        if(L<=l&&r<=R){
            return sum[rt]%p;
        }
        pushdown(l,r,rt);
        ll ans=0;
        int mid=(l+r)>>1;
        if(L<=mid)ans+=query(L,R,l,mid,rt<<1);
        if(mid+1<=R)ans+=query(L,R,mid+1,r,rt<<1|1);
        return ans%p;
    }
    int main(){
        int n,m;
        scanf("%d %d %lld",&n,&m,&p);
        build(1,n,1);
        for(int i=1;i<=m;i++){
            int g;
            scanf("%d",&g);
            if(g==1){
                int l,r;
                ll c;
                scanf("%d %d %lld",&l,&r,&c);
                update(l,r,1,n,1,c,0);
            }
            else if(g==2){
                int l,r;
                ll c;
                scanf("%d %d %lld",&l,&r,&c);
                update(l,r,1,n,1,1,c);
            }
            else{
                int l,r;
                scanf("%d %d",&l,&r);
                printf("%lld
    ",query(l,r,1,n,1));
            }
        }
        return 0;
    }

    end

  • 相关阅读:
    长沙雅礼中学集训-------------------day1(内含day0)
    17年 5月份刷题版
    manecher_回文串;
    后缀数组
    湖南集训
    好像又好久没更了;计算课noip模拟赛;
    dp的练习题;
    oj1638
    【noi】植物大战僵尸
    #日常吐槽
  • 原文地址:https://www.cnblogs.com/stone41123/p/7581274.html
Copyright © 2011-2022 走看看