zoukankan      html  css  js  c++  java
  • 【模板】线段树&树状数组&ST表

    树状数组:单点修改+区间查询

    #include<bits/stdc++.h>
    #define ri register int
    #define ll long long
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    const int M=5e5+5;
    int n,m,k,a,b,c[M];
    inline int lowbit(int x){return x&(-x);}
    inline void updata(int x,int y){for(;x<=n;x+=lowbit(x))c[x]+=y;}
    inline int sum(int x){
        int ans=0;
        for(;x;x-=lowbit(x))ans+=c[x]; 
        return ans;
    }
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    int main(){
        n=read(),m=read();
        For(i,1,n){
            updata(i,read());
        }
        For(i,1,m){
            k=read(),a=read(),b=read();
            if(k==1){
                updata(a,b);
            }
            else{
                printf("%d
    ",sum(b)-sum(a-1));
            }
        }
        return 0;
    }

    树状数组:区间修改+单点查询

    #include<bits/stdc++.h>
    #define ri register int
    #define ll long long
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    const int M=5e5+5;
    ll n,m,c[M],v[M],k,a,b,d,x;
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    inline int lowbit(int x){return x&(-x);}
    inline void updata(int x,int y){for(;x<=n;x+=lowbit(x)){c[x]+=y;}}
    inline ll sum(int x){
        int ans=0;
        for(;x;x-=lowbit(x)){
            ans+=c[x];
        }
        return ans;
    }
    int main(){
        n=read(),m=read();
        For(i,1,n){
            v[i]=read();
            updata(i,v[i]-v[i-1]);
        }
        For(i,1,m){
            k=read();
            if(k==1){
                a=read(),b=read(),d=read();
                updata(a,d);updata(b+1,-d);
            }
            else{
                x=read();
                printf("%d
    ",sum(x));
            }
        }
        return 0;
    }

    线段树:加法

    #include<bits/stdc++.h>
    #define ri register int
    #define ll long long
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    const int M=1e5+5;
    ll n,m,a[M],k,x,y,d;
    struct node{
        ll l,r,lz,s;
    }tr[M*4];
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    inline void B_T(int i,int l,int r){
        tr[i].l=l,tr[i].r=r;
        if(l==r){tr[i].s=a[l];return;}
        int mid=(l+r)>>1;
        B_T(i<<1,l,mid),B_T(i<<1|1,mid+1,r);
        tr[i].s+=tr[i<<1].s+tr[i<<1|1].s;
    }
    inline void D_T(int i){
        tr[i<<1].lz+=tr[i].lz;
        tr[i<<1].s+=(tr[i<<1].r-tr[i<<1].l+1)*tr[i].lz;
        tr[i<<1|1].lz+=tr[i].lz;
        tr[i<<1|1].s+=(tr[i<<1|1].r-tr[i<<1|1].l+1)*tr[i].lz;
        tr[i].lz=0;
    }
    inline void U_T(int i,int l,int r,int v){
        if(tr[i].l>r||tr[i].r<l)return;
        if(tr[i].l>=l&&tr[i].r<=r){
            tr[i].lz+=v;
            tr[i].s+=(tr[i].r-tr[i].l+1)*v;
            return;
        }
        if(tr[i].lz) D_T(i);
        U_T(i<<1,l,r,v),U_T(i<<1|1,l,r,v);
        tr[i].s=tr[i<<1].s+tr[i<<1|1].s; 
    }
    inline ll Q_T(int i,int l,int r){
        if(tr[i].l>r||tr[i].r<l) return 0;
        if(tr[i].l>=l&&tr[i].r<=r) return tr[i].s;
        if(tr[i].lz) D_T(i);
        return Q_T(i<<1,l,r)+Q_T(i<<1|1,l,r);
    }
    int main(){
        n=read(),m=read();
        For(i,1,n) a[i]=read();
        B_T(1,1,n);
        For(i,1,m){
            k=read();
            if(k==1){
                x=read(),y=read(),d=read();
                U_T(1,x,y,d);
            }
            else{
                x=read(),y=read();
                printf("%lld
    ",Q_T(1,x,y));
            }
        }
        return 0;
    }

    线段树:乘法

    #include<bits/stdc++.h>
    #define ri register int
    #define ll long long
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    const int M=1e5+5;
    ll n,m,p,a[M],k,x,y,d,c;
    struct node{
        ll l,r,s,mlz,plz;
    }tr[4*M];
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    inline void B_T(ll i,ll l,ll r){
        tr[i].l=l,tr[i].r=r,tr[i].mlz=1;
        if(l==r){tr[i].s=a[l]%p;return;}
        ll mid=(l+r)>>1;
        B_T(i<<1,l,mid),B_T(i<<1|1,mid+1,r);
        tr[i].s=(tr[i<<1].s+tr[i<<1|1].s)%p;
        return;
    }
    inline void P_T(ll i){
        ll k1=tr[i].mlz,k2=tr[i].plz;
        tr[i<<1].s=(tr[i<<1].s*k1+(tr[i<<1].r-tr[i<<1].l+1)*k2)%p;
        tr[i<<1].mlz=(tr[i<<1].mlz*k1)%p;
        tr[i<<1].plz=(tr[i<<1].plz*k1+k2)%p;
        tr[i<<1|1].s=(tr[i<<1|1].s*k1+(tr[i<<1|1].r-tr[i<<1|1].l+1)*k2)%p;
        tr[i<<1|1].mlz=(tr[i<<1|1].mlz*k1)%p;
        tr[i<<1|1].plz=(tr[i<<1|1].plz*k1+k2)%p;
        tr[i].plz=0,tr[i].mlz=1;
        return;
    }
    inline void M_T(ll i,ll l,ll r,ll d){
        if(tr[i].l>r||tr[i].r<l) return;
        if(tr[i].l>=l&&tr[i].r<=r){
            tr[i].s=(tr[i].s*d)%p;
            tr[i].mlz=(tr[i].mlz*d)%p;
            tr[i].plz=(tr[i].plz*d)%p;
            return;
        }
        P_T(i);
        if(tr[i<<1].r>=l) M_T(i<<1,l,r,d);
        if(tr[i<<1|1].l<=r) M_T(i<<1|1,l,r,d);
        tr[i].s=(tr[i<<1].s+tr[i<<1|1].s)%p;
        return;
    }
    inline void A_T(ll i,ll l,ll r,ll d){
        if(tr[i].l>r||tr[i].r<l)return;
        if(tr[i].l>=l&&tr[i].r<=r){
            tr[i].s+=((tr[i].r-tr[i].l+1)*d)%p;
            tr[i].plz=(tr[i].plz+d)%p;
            return;
        }
        P_T(i);
        if(tr[i<<1].r>=l) A_T(i<<1,l,r,d);
        if(tr[i<<1|1].l<=r) A_T(i<<1|1,l,r,d);
        tr[i].s=(tr[i<<1].s+tr[i<<1|1].s)%p;
        return;
    }
    inline ll Q_T(ll i,ll l,ll r){
        if(tr[i].r<l||tr[i].l>r)return 0;
        if(tr[i].r<=r&&tr[i].l>=l) return tr[i].s;
        P_T(i);
        ll sum=0;
        if(tr[i<<1].r>=l) sum+=Q_T(i<<1,l,r)%p;
        if(tr[i<<1|1].l<=r) sum+=Q_T(i<<1|1,l,r)%p;
        return sum%p;
    }
    int main(){
        n=read(),m=read(),p=read();
        For(i,1,n) a[i]=read();
        B_T(1,1,n);
        For(i,1,m){
            k=read();
            if(k==1){
                x=read(),y=read(),c=read()%p;
                M_T(1,x,y,c);
            }
            else if(k==2){
                x=read(),y=read(),c=read()%p;
                A_T(1,x,y,c);
            }
            else{
                x=read(),y=read();
                printf("%lld
    ",Q_T(1,x,y));
            }
        }
        return 0;
    }

    线段树:开根号

    #include<bits/stdc++.h>
    #define ri register int
    #define ll long long
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    const int M=1e5+5;
    struct node{
        ll l,r,lz,s,maxx,minn;
    }tr[M*4];
    ll n,m,a[M],k,x,y;
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    inline void B_T(int i,int l,int r){
        tr[i].l=l,tr[i].r=r;
        if(l==r){tr[i].s=tr[i].minn=tr[i].maxx=a[l];return;}
        int mid=(l+r)>>1;
        B_T(i<<1,l,mid),B_T(i<<1|1,mid+1,r);
        tr[i].s=tr[i<<1].s+tr[i<<1|1].s;
        tr[i].minn=min(tr[i<<1].minn,tr[i<<1|1].minn);
        tr[i].maxx=max(tr[i<<1].maxx,tr[i<<1|1].maxx);
        return;
    }
    inline void P_T(int i){
        ll k=tr[i].lz;
        tr[i<<1].lz+=k;
        tr[i<<1].s-=(tr[i<<1].r-tr[i<<1].l+1)*k;
        tr[i<<1].minn-=k;
        tr[i<<1].maxx-=k;
        tr[i<<1|1].lz+=k;
        tr[i<<1|1].s-=(tr[i<<1|1].r-tr[i<<1|1].l+1)*k;
        tr[i<<1|1].minn-=k;
        tr[i<<1|1].maxx-=k;
        tr[i].lz=0;
        return;
    }
    inline void S_T(int i,int l,int r){
        if(tr[i].r<l||tr[i].l>r)return;
        if(tr[i].l>=l&&tr[i].r<=r&&(tr[i].minn-(ll)sqrt(tr[i].minn))==(tr[i].maxx-(ll)sqrt(tr[i].maxx))){
            ll k=tr[i].minn-(ll)sqrt(tr[i].minn);
            tr[i].lz+=k;
            tr[i].s-=(tr[i].r-tr[i].l+1)*k;
            tr[i].minn-=k;
            tr[i].maxx-=k;
            return;
        }
        if(tr[i].lz) P_T(i);
        if(tr[i<<1].r>=l) S_T(i<<1,l,r);
        if(tr[i<<1|1].l<=r) S_T(i<<1|1,l,r);
        tr[i].s=tr[i<<1].s+tr[i<<1|1].s;
        tr[i].minn=min(tr[i<<1].minn,tr[i<<1|1].minn);
        tr[i].maxx=max(tr[i<<1].maxx,tr[i<<1|1].maxx);
        return;
    }
    inline ll Q_T(int i,int l,int r){
        if(tr[i].l>r||tr[i].r<l) return 0;
        if(tr[i].l>=l&&tr[i].r<=r) return tr[i].s;
        if(tr[i].lz) P_T(i);
        ll ans=0;
        if(tr[i<<1].r>=l) ans+=Q_T(i<<1,l,r);
        if(tr[i<<1|1].l<=r) ans+=Q_T(i<<1|1,l,r);
        return ans;
    }
    int main(){
        n=read();
        For(i,1,n) a[i]=read();
        B_T(1,1,n);
        m=read();
        For(i,1,m){
            k=read(),x=read(),y=read();
            if(x>y) swap(x,y);
            if(k==1){
                printf("%lld
    ",Q_T(1,x,y));
            }
            else{
                S_T(1,x,y);
            }
        }
        return 0;
    }
  • 相关阅读:
    线性表——(2)单向链表
    线性表——(1)顺序表
    UVa 1592 数据库
    UVa 12096 集合栈计算机
    Python 协程
    Python 多线程及进程
    Python 日志(Log)
    Python 函数式编程
    Python基础
    DB2 获取前两天的数据
  • 原文地址:https://www.cnblogs.com/jian-song/p/11835700.html
Copyright © 2011-2022 走看看