【模板】线段树&树状数组&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\n",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\n",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\n",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\n",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\n",Q_T(1,x,y)); } else{ S_T(1,x,y); } } return 0; }