1. 程式人生 > 實用技巧 >線段樹(模板)

線段樹(模板)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
    int x=0;int f=1;char c=getchar();
    while(c<'0' || c>'9'){if(c=='-') f=0;c=getchar();}
    while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return f?x:-x;
}
const int N=1e5+10;
int a[N],n,m;
struct SGT
{
    int l,r;
    ll add,sum;
}t[N<<2];
void build(int u,int l,int r)
{
    t[u].l=l;
    t[u].r=r;
    if(l==r)
    {
        t[u].sum=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build((u<<1),l,mid);
    build(((u<<1)|1),mid+1,r);
    t[u].sum=t[(u<<1)].sum+t[((u<<1)|1)].sum;
}
void spread(int u)
{
    if(t[u].add)
    {
        t[(u<<1)].add+=t[u].add;
        t[((u<<1)|1)].add+=t[u].add;
        t[(u<<1)].sum+=(t[(u<<1)].r-t[(u<<1)].l+1)*t[u].add;
        t[((u<<1)|1)].sum+=(t[((u<<1)|1)].r-t[((u<<1)|1)].l+1)*t[u].add;
        t[u].add=0;
    }
}
void modify(int u,int l,int r,int d)
{
    if(l<=t[u].l && t[u].r<=r)
    {
        t[u].add+=d;
        t[u].sum+=(t[u].r-t[u].l+1)*d;
        return;
    }
    spread(u);
    int mid=(t[u].l+t[u].r)>>1;
    if(l<=mid) modify((u>>1),l,r,d);
    if(r>mid) modify(((u<<1)|1),l,r,d);
    t[u].sum=t[(u<<1)].sum+t[((u<<1)|1)].sum;
}
ll query(int u,int l,int r)
{
    if(l<=t[u].l && t[u].r<=r) return t[u].sum;
    ll ans=0;
    spread(u);
    int mid=(t[u].l+t[u].r)>>1;
    if(l<=mid) ans+=query((u<<1),l,r);
    if(mid<r) ans+=query(((u<<1)|1),l,r);
    return ans;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int op=read();
        if(op==1)
        {
            int l=read(),r=read(),d=read();
            modify(1,l,r,d);
        }
        else
        {
            int l=read(),r=read();
            printf("%lld\n",query(1,l,r));
        }
    }
    return 0;
}