• 线段树


    区间加&区间求和

    P3372【模板】线段树1

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 400010
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
        x=0; bool flag=0; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
        for(;isdigit(c);c=getchar()) x=x*10+(c^48);
        if(flag) x=-x;
    }
    
    ll n,m,s[maxn],num,x,y,k;
    ll t[maxn],tag[maxn];
    
    void pushup(ll x){
        t[x]=t[x<<1]+t[x<<1|1];//=t[2*x]+t[2*x+1] 
    }
    
    void build(ll x,ll l,ll r){
        if(l==r){
            t[x]=s[l];
            return ;
        }
        ll mid=(l+r)>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        pushup(x);
    }
    
    void tag_(ll x,ll len,ll k){
        t[x]+=len*k;
        tag[x]+=k;
    }
    
    void pushdown(ll x,ll l,ll r){
        if(tag[x]){
            ll mid=(l+r)>>1;
            tag_(x<<1,mid-l+1,tag[x]);
            tag_(x<<1|1,r-mid,tag[x]);
            tag[x]=0;
        }
    }
    
    void change(ll x,ll l,ll r,ll cl,ll cr,ll k){
        pushdown(x,l,r);
        if(cl<=l&&r<=cr) return tag_(x,r-l+1,k);
        ll mid=(l+r)>>1;
        if(cl<=mid) change(x<<1,l,mid,cl,cr,k);
        if(cr>=mid+1) change(x<<1|1,mid+1,r,cl,cr,k);
        pushup(x);
    }
    
    ll query(ll x,ll l,ll r,ll ql,ll qr){
        pushdown(x,l,r);
        if(ql<=l&&r<=qr) return t[x];
        ll mid=(l+r)>>1;
        ll ret=0;
        if(ql<=mid) ret+=query(x<<1,l,mid,ql,qr);
        if(qr>=mid+1) ret+=query(x<<1|1,mid+1,r,ql,qr);
        return ret;
    }
    
    int main(){
        read(n),read(m);
        for(int i=1;i<=n;i++) read(s[i]);
        build(1,1,n);
        for(int i=1;i<=m;i++){
            cin>>num;
            if(num==1) {
                cin>>x>>y>>k;
                change(1,1,n,x,y,k);
            }
            if(num==2) {
                cin>>x>>y;
                cout<<query(1,1,n,x,y)<<endl;
            }
        }
        return 0;
    }

     70分 ↑

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 800010
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
        x=0; bool flag=0; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
        for(;isdigit(c);c=getchar()) x=x*10+(c^48);
        if(flag) x=-x;
    }
    
    ll n,m,s[maxn],num,x,y,k;
    ll t[maxn],tag[maxn]; 
    
    void pushup(ll x){
        t[x]=t[x<<1]+t[x<<1|1];//=t[2*x]+t[2*x+1] 
    }
    
    void build(ll x,ll l,ll r){
        if(l==r){
            t[x]=s[l];
            return ;
        }
        ll mid=(l+r)>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        pushup(x);
    }
    
    void tag_(ll x,ll len,ll k){
        t[x]+=len*k;
        tag[x]+=k;
    }
    
    void pushdown(ll x,ll l,ll r){
        if(tag[x]){
            ll mid=(l+r)>>1;
            tag_(x<<1,mid-l+1,tag[x]);
            tag_(x<<1|1,r-mid,tag[x]);
            tag[x]=0;
        }
    }
    
    void change(ll x,ll l,ll r,ll cl,ll cr,ll k){
        pushdown(x,l,r);
        if(cl<=l&&r<=cr) {tag_(x,r-l+1,k); return ;}
        ll mid=(l+r)>>1;
        if(cl<=mid) change(x<<1,l,mid,cl,cr,k);
        if(cr>=mid+1) change(x<<1|1,mid+1,r,cl,cr,k);
        pushup(x);
    }
    
    ll query(ll x,ll l,ll r,ll ql,ll qr){
        pushdown(x,l,r);
        if(ql<=l&&r<=qr) return t[x];
        ll mid=(l+r)>>1;
        ll ret=0;
        if(ql<=mid) ret+=query(x<<1,l,mid,ql,qr);
        if(qr>=mid+1) ret+=query(x<<1|1,mid+1,r,ql,qr);
        return ret;
    }
    
    int main(){
        read(n),read(m);
        for(int i=1;i<=n;i++) read(s[i]);
        build(1,1,n);
        for(int i=1;i<=m;i++){
            cin>>num;
            if(num==1) {
                cin>>x>>y>>k;
                change(1,1,n,x,y,k);
            }
            if(num==2) {
                cin>>x>>y;
                cout<<query(1,1,n,x,y)<<endl;
            }
        }
        return 0;
    }

    AC ↑

    我也不知道为啥4倍空间过不了要开8倍才能过

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 400010
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
        x=0; bool flag=0; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
        for(;isdigit(c);c=getchar()) x=x*10+(c^48);
        if(flag) x=-x;
    }
    
    ll n,m,s[maxn],num,x,y,k;
    ll t[maxn],tag[maxn]; 
    
    void pushup(ll x){
        t[x]=t[x<<1]+t[x<<1|1];//=t[2*x]+t[2*x+1] 
    }
    
    void build(ll x,ll l,ll r){
        if(l==r){
            t[x]=s[l];
            return ;
        }
        ll mid=(l+r)>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        pushup(x);
    }
    
    void tag_(ll x,ll len,ll k){
        t[x]+=len*k;
        tag[x]+=k;
    }
    
    void pushdown(ll x,ll l,ll r){
        if(tag[x]){
            ll mid=(l+r)>>1;
            tag_(x<<1,mid-l+1,tag[x]);
            tag_(x<<1|1,r-mid,tag[x]);
            tag[x]=0;
        }
    }
    
    void change(ll x,ll l,ll r,ll cl,ll cr,ll k){
        if(cl<=l&&r<=cr) {tag_(x,r-l+1,k); return ;}
        pushdown(x,l,r);
        ll mid=(l+r)>>1;
        if(cl<=mid) change(x<<1,l,mid,cl,cr,k);
        if(cr>=mid+1) change(x<<1|1,mid+1,r,cl,cr,k);
        pushup(x);
    }
    
    ll query(ll x,ll l,ll r,ll ql,ll qr){
        if(ql<=l&&r<=qr) return t[x];
        pushdown(x,l,r);
        ll mid=(l+r)>>1;
        ll ret=0;
        if(ql<=mid) ret+=query(x<<1,l,mid,ql,qr);
        if(qr>=mid+1) ret+=query(x<<1|1,mid+1,r,ql,qr);
        return ret;
    }
    
    int main(){
        read(n),read(m);
        for(int i=1;i<=n;i++) read(s[i]);
        build(1,1,n);
        for(int i=1;i<=m;i++){
            cin>>num;
            if(num==1) {
                cin>>x>>y>>k;
                change(1,1,n,x,y,k);
            }
            if(num==2) {
                cin>>x>>y;
                cout<<query(1,1,n,x,y)<<endl;
            }
        }
        return 0;
    }

    AC ↑

    好了我知道了,千万注意pushdown要放在return后面,这样4倍空间就能过了~

    区间乘&区间加&区间求和

    P3373【模板】线段树2

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 400010
    #define ll long long
    using namespace std;
    template<typename T>
    inline void read(T &x){
        x=0; bool flag=0; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
        for(;isdigit(c);c=getchar()) x=x*10+(c^48);
        if(flag) x=-x;
    }
    
    ll n,m,p,s[maxn],num,x,y,k;
    ll t[maxn],tag1[maxn],tag2[maxn];//tag1->mul tag2->sum
    
    void pushup(ll x){
        (t[x]=t[2*x]+t[2*x+1])%=p;
    }
    
    void build(ll x,ll l,ll r){
        tag1[x]=1,tag2[x]=0;
        if(l==r){
            t[x]=s[l];
            return ;
        }
        ll mid=(l+r)/2;
        build(x*2,l,mid);
        build(x*2+1,mid+1,r);
        pushup(x);
    }
    
    void pushdown(ll x,ll l,ll r){
        ll mid=(l+r)/2;
        t[x*2]=(t[x*2]*tag1[x]%p+(mid-l+1)*tag2[x])%p;
        t[x*2+1]=(t[x*2+1]*tag1[x]%p+(r-mid)*tag2[x])%p;
        tag1[x*2]=tag1[x*2]*tag1[x]%p;
        tag1[x*2+1]=tag1[x*2+1]*tag1[x]%p;
        tag2[x*2]=(tag2[x*2]*tag1[x]+tag2[x])%p;
        tag2[x*2+1]=(tag2[x*2+1]*tag1[x]+tag2[x])%p;
        tag1[x]=1,tag2[x]=0;
    }
    
    /*
    一定要先乘后加( 没人愿意乘法逆元先加后乘吧......
    (a+b)*c=a*c+b*c;
    a*c+b=a*c+b; 
    */
    void mul(ll x,ll l ,ll r,ll cl,ll cr,ll k){
        if(cl<=l&&r<=cr){
            (t[x]*=k)%=p;
            (tag1[x]*=k)%=p;
            (tag2[x]*=k)%=p;
            return ;
        }
        pushdown(x,l,r);
        ll mid=(l+r)/2;
        if(cl<=mid) mul(x*2,l,mid,cl,cr,k);
        if(cr>=mid+1) mul(x*2+1,mid+1,r,cl,cr,k);
        pushup(x);
    }
    
    void sum(ll x,ll l ,ll r,ll cl,ll cr,ll k){
        if(cl<=l&&r<=cr){
            (t[x]+=(r-l+1)*k%p)%=p;
            (tag2[x]+=k)%=p;
            return ;
        }
        pushdown(x,l,r);
        ll mid=(l+r)/2;
        if(cl<=mid) sum(x*2,l,mid,cl,cr,k);
        if(cr>=mid+1) sum(x*2+1,mid+1,r,cl,cr,k);
        pushup(x);
    }
    
    ll query(ll x,ll l,ll r,ll ql,ll qr){
        if(ql<=l&&r<=qr) return t[x];
        pushdown(x,l,r);
        ll mid=(l+r)/2,ret=0;
        if(ql<=mid) (ret+=query(x*2,l,mid,ql,qr))%=p;
        if(qr>=mid+1) (ret+=query(x*2+1,mid+1,r,ql,qr))%=p;
        return ret;
    }
    
    int main(){
        read(n),read(m),read(p);
        for(int i=1;i<=n;i++) read(s[i]);
        build(1,1,n);
        for(int i=1;i<=m;i++){
            read(num);read(x),read(y);
            if(num==1){
                read(k);
                mul(1,1,n,x,y,k);
            }
            if(num==2){
                read(k);
                sum(1,1,n,x,y,k);
            }
            if(num==3){
                cout<<query(1,1,n,x,y)%p<<endl;
            }
        }
        return 0;
    } 
  • 相关阅读:
    进程和线程
    关于offer对比
    CVTE面经
    重定向
    奇虎360面试经验
    百纳信息(海豚浏览器)面经
    携程网面经
    百度面经
    位运算
    Cracking the Coding Interview 4.8
  • 原文地址:https://www.cnblogs.com/DReamLion/p/14401211.html
Copyright © 2020-2023  润新知