【模板】线段树&树状数组&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;
}
原文地址:https://www.cnblogs.com/jian-song/p/11835700.html