线段树(区间加区间统计)

Posted reshuffle

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树(区间加区间统计)相关的知识,希望对你有一定的参考价值。

#include <bits/stdc++.h>    
#define ll long long
using namespace std;
const ll maxn=2e5*5+10;
struct re
{
    ll x,y,w,z;
};
re a[maxn];
ll b[maxn];
void up(ll k)
{
    a[k].z=a[k*2].z+a[k*2+1].z;
}
void down(ll k)
{
    a[k*2].w+=a[k].w;
    a[k*2].z+=(a[k*2].y-a[k*2].x+1)*a[k].w;
    a[k*2+1].w+=a[k].w;
    a[k*2+1].z+=(a[k*2+1].y-a[k*2+1].x+1)*a[k].w;   
    a[k].w=0;
}
void build(ll k,ll l,ll r)
{
    a[k].x=l,a[k].y=r,a[k].w=0;
    if (l==r)
    {       
        a[k].z=b[l];
        return;
    }
    ll mid=(l+r)/2;
    build(k*2,l,mid);
    build(k*2+1,mid+1,r);
    up(k);
}
void update(ll k,ll l,ll r,ll w)
{
    if (a[k].y<l||a[k].x>r) return;
    if (l<=a[k].x&&a[k].y<=r)
    {
        a[k].w+=w;
        a[k].z+=(a[k].y-a[k].x+1)*w;    
        return;
    }
    if (a[k].w) down(k);
    update(k*2,l,r,w);
    update(k*2+1,l,r,w);
    up(k);
}
ll query(ll k,ll l,ll r)
{
    if (a[k].y<l||a[k].x>r) return 0;
    if (l<=a[k].x&&a[k].y<=r) return a[k].z;
    if (a[k].w) down(k);
    return query(k*2,l,r)+query(k*2+1,l,r);
}
int main()
{
    ll n,m;
    cin>>n>>m;
    for (ll i=1;i<=n;i++) scanf("%lld",&b[i]);
    build(1,1,n);

    for (ll i=1;i<=m;i++)
    {
        ll x,y,z,w;
        scanf("%lld%lld%lld",&x,&y,&z);
        if (x==1)
        {
            scanf("%lld",&w);
            update(1,y,z,w);
        }
        else printf("%lld
",query(1,y,z)); 
//      for (ll j=1;j<=10;j++) printf("%lld %lld %lld %lld
",a[j].x,a[j].y,a[j].w,a[j].z);
    }
    
}

以上是关于线段树(区间加区间统计)的主要内容,如果未能解决你的问题,请参考以下文章

树状数组区间加区间求和

uoj#228. 基础数据结构练习题(线段树)

线段树的思路

线段树基础

线段树

线段树 建树 单点修改 点点/区间查询