线段树

关于对线段树模板的简化:

在刚开始学线段树时,我们学习的是利用完全二叉树的性质来建立子节点:左儿子的节点等于父亲节点序号乘2,右儿子的节点的序号等于左儿子的节点数加1,并且选用结构体的方式来存储信息。大概就是这样一个思路。

由于考虑到结构体引用慢,并且在可持久化线段树(主席树)中,已经不满足完全二叉树的性质,为了统一线段树的写法,建议大家统一使用动态开节点建树的方法。变量名的改变变化不大,列举如下:
lson[p]表示p节点的左儿子编号(注意是编号!!!不是维护序列的区间!!)rson[p]同理。
sum[p]表示一段区间,其他信息可以自行维护。
ndnum表示节点个数。
root表示根节点。
那么细节就看代码吧。

#include

#define maxn 400000

using namespace std;

long long root,a[maxn],n,m,lson[maxn],rson[maxn],ll[maxn],rr[maxn],ndnum=0,add[maxn],sum[maxn],L,R;

void down(long long t)
{
    if(add[t])
    {
        sum[lson[t]]+=add[t]*(rr[lson[t]]-ll[lson[t]]+1);
        sum[rson[t]]+=add[t]*(rr[rson[t]]-ll[rson[t]]+1);
        add[lson[t]]+=add[t];
        add[rson[t]]+=add[t];
        add[t]=0;
    }
}
void update(long long t)
{
    sum[t]=sum[lson[t]]+sum[rson[t]];
    return;
}
void build(long long &t,long long l,long long r)//t是带了地址符号的!!
{
    t=++ndnum;//动态开节点
    ll[t]=l;rr[t]=r;
    if(l==r)
    {
        sum[t]=a[l];add[t]=0;
        return;
    }
    long long mid=(l+r)/2;
    build(lson[t],l,mid);
    build(rson[t],mid+1,r);
    update(t);
}
void modify(long long t,long long l,long long r,long long k)
{
    if(L<=l&&r<=R)
    {
        sum[t]+=k*(r-l+1);
        add[t]+=k;
        return;
    }
    down(t);
    long long mid=(l+r)/2;
    if(L<=mid) modify(lson[t],l,mid,k);
    if(R>mid)  modify(rson[t],mid+1,r,k);
    update(t);
}
long long query(long long t,long long l,long long r)
{
    if(L<=l&&r<=R) return sum[t];
    down(t);
    long long mid=(l+r)/2;
    long long ans=0;
    if(L<=mid) ans+=query(lson[t],l,mid);
    if(R>mid)  ans+=query(rson[t],mid+1,r);
    return ans;
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for(long long i=1;i<=n;++i)
    scanf("%lld",&a[i]);
    build(root,1,n);
    for(int i=1;i<=m;++i)
    {
        long long op,k;
        scanf("%lld",&op);
        if(op==1)
        {
            scanf("%lld%lld%lld",&L,&R,&k);
            modify(root,1,n,k);
        }
        else
        {
            scanf("%lld%lld",&L,&R);
            printf("%lld\n",query(root,1,n));
        }
    }
    return 0;
}

你可能感兴趣的:(数据结构,线段树,线段树模板)