码迷,mamicode.com
首页 > 其他好文 > 详细

线段树小记

时间:2020-07-23 23:26:54      阅读:100      评论:0      收藏:0      [点我收藏+]

标签:str   long   clu   i++   build   原来   线段   void   struct   

普通线段树可以[先标记\(tag\)后更改]或[边推\(tag\)边更改]

打算从原来的[先标记\(tag\)后更改]改变为较为普及的[边推\(tag\)边更改]

这里放模板题代码

#include<cstdio>
#include<iostream>
#define N 100005
#define ll long long
using namespace std;
struct node
{
    int l,r;
    ll s,lz;
}t[N << 2];
ll a[N];
int n,m,opt,x,y;
ll z;
void merge(int p)
{
    t[p].s=t[p+p].s+t[p+p+1].s;
}
void build(int p,int l,int r)
{
    t[p].l=l,t[p].r=r;
    if (l==r)
    {
        t[p].s=a[l];
        t[p].lz=0;
        return;
    }
    int mid=(l+r) >> 1;
    build(p+p,l,mid);
    build(p+p+1,mid+1,r);
    merge(p);
}
void down_tag(int p,ll z)
{
    t[p].s+=z*(t[p].r-t[p].l+1);
    t[p].lz+=z;
}
void down(int p)
{
    down_tag(p+p,t[p].lz),down_tag(p+p+1,t[p].lz);
    t[p].lz=0;
}
void change(int p,int x,int y,ll z)
{
    if (t[p].l>y||t[p].r<x)
        return;
    if (t[p].l>=x&&t[p].r<=y)
    {
        t[p].s+=z*(t[p].r-t[p].l+1);
        t[p].lz+=z;
        return;
    }
    down(p);
    change(p+p,x,y,z);
    change(p+p+1,x,y,z);
    merge(p);
}
ll calc(int p,int x,int y)
{
    if (t[p].l>y||t[p].r<x)
        return 0;
    if (t[p].l>=x&&t[p].r<=y)
        return t[p].s;
    down(p);
    return calc(p+p,x,y)+calc(p+p+1,x,y);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    build(1,1,n);
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&opt);
        switch (opt)
        {
            case 1:
                scanf("%d%d%lld",&x,&y,&z);
                change(1,x,y,z);
                break;
            case 2:
                scanf("%d%d",&x,&y);
                printf("%lld\n",calc(1,x,y));
                break;
        }
    }
}

线段树小记

标签:str   long   clu   i++   build   原来   线段   void   struct   

原文地址:https://www.cnblogs.com/GK0328/p/13368580.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!