P3372 【模板】线段树 1

原题传送门

#include 
using namespace std;

const int N = 1000001;
typedef long long ll;

ll n,m,a[N],ans[N<<2],tag[N<<2];

inline ll leftSon(ll x)
{
    return x<<1;
}

inline ll rightSon(ll x)
{
    return x<<1|1;
} 

inline void modifyUp(ll p)
{
    ans[p]=ans[leftSon(p)]+ans[rightSon(p)];
}

inline void buildTree(ll p,ll l,ll r)
{
    tag[p]=0;
    if(l==r)
    {
        ans[p]=a[l];
        return;
    }
    ll mid=(l+r)>>1;
    
    buildTree(leftSon(p),l,mid);
    buildTree(rightSon(p),mid+1,r);
    
    modifyUp(p);
}

inline void addToRoot(ll p,ll l,ll r,ll k)
{
    tag[p]+=k;
    ans[p]+=k*(r-l+1);
}

inline void modifyDown(ll p,ll l,ll r)
{
    ll mid=(l+r)>>1;
    addToRoot(leftSon(p),l,mid,tag[p]);
    addToRoot(rightSon(p),mid+1,r,tag[p]);
    tag[p]=0;
}

inline void updateTree(ll newl,ll newr,ll l,ll r,ll p,ll k)
{
    if(newl<=l&&r<=newr)
    {
        ans[p]+=k*(r-l+1);
        tag[p]+=k;
        return;
    }
    modifyDown(p,l,r);
    
    ll mid=(l+r)>>1;
    if(newl<=mid)
    {
        updateTree(newl,newr,l,mid,leftSon(p),k);
    }
    if(newr>mid)
    {
        updateTree(newl,newr,mid+1,r,rightSon(p),k);
    }
    
    modifyUp(p);
}

ll query(ll qx,ll qy,ll l,ll r,ll p)
{
    ll res=0;
    if(qx<=l&&r<=qy)
    {
        return ans[p];
    }
    ll mid=(l+r)>>1;
    modifyDown(p,l,r);
    if(qx<=mid)
    {
        res+=query(qx,qy,l,mid,leftSon(p));
    }
    if(qy>mid) 
    {
        res+=query(qx,qy,mid+1,r,rightSon(p));
    }
    return res;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    ll n,m;
    cin>>n>>m;
    
    for(ll i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    
    buildTree(1,1,n);
    
    ll ask,b,c,d,e,f;
    for(int k=1;k<=m;k++)
    {
        cin>>ask;
        if(ask==1)
        {
            cin>>b>>c>>d;
            updateTree(b,c,1,n,1,d);
        }
        else
        {
            cin>>e>>f;
            cout<<query(e,f,1,n,1)<<endl;
        }
    }
}

你可能感兴趣的:(线段树,板)