前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线段树(模板)

线段树(模板)

作者头像
Here_SDUT
发布2022-06-29 15:08:11
3030
发布2022-06-29 15:08:11
举报
文章被收录于专栏:机器学习炼丹之旅

刚学了线段树,趁现在理解比较清楚,写篇博客供以后翻阅,线段树有很多应用,如求区间总和,最大值,最小值等,总之求区间问题都可以想想线段树,这里以求和为例

定义全局变量

代码语言:javascript
复制
const int maxn=1e5+10;
struct node
{
    int L,R;//当前节点的左右区间
    long long big,sum,lazy;//数据类型根据题意改,sum为当前节点的总和
} tree[4*maxn];//开四倍于数据量的空间

回溯函数

代码语言:javascript
复制
void pushup(int p)
{
    tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;
}

建树

代码语言:javascript
复制
void build(int l,int r,int p)
{
    tree[p].L=l,tree[p].R=r,tree[p].lazy=0;//给当前节点的左右区间和lazy初始值
    if(l==r)//叶子节点为递归边界
    {
        scanf("%lld",&tree[p].sum); //这里直接写入,减少使用一个存放数据的数组
        return ;//一定要return掉哦~
    }
    int mid=(l+r)/2;
    build(l,mid,2*p);//向左递归
    build(mid+1,r,p*2+1);//向右递归
    pushup(p);//回溯改变父亲节点的值
}

下压函数

代码语言:javascript
复制
//用于区间查询和区间修改,根据当前节点的lazy_tag改变儿子节点的数据
void pushdown(int p,int l,int r)//这里的l,r为左右孩子在待求区间里的个数,参照下面的查询函数理解
{
    if(tree[p].lazy)
    {
        tree[p*2].lazy+=tree[p].lazy;//改变儿子节点的lazy_tag
        tree[p*2+1].lazy+=tree[p].lazy;
        tree[p*2].sum+=tree[p].lazy*l;//根据当前节点lazy_tag改变儿子节点的值,这里可以体现lazy的延迟性
        tree[p*2+1].sum+=tree[p].lazy*r;
        tree[p].lazy=0;//当前节点的lazy变为0,完成下压操作
    }
}

区间查询

代码语言:javascript
复制
long long Quary(int a,int b,int p)//a,b为待求区间,p为当前节点的下标
{
    long long awn=0;//输出的待求区间的总和
    int l=tree[p].L;
    int r=tree[p].R;
    if(a<=l&&r<=b)//如果待求区间比当前节点包含的区间大,直接返回当前区间的值
    {
        return tree[p].sum;
    }
    int mid=(l+r)/2;
    pushdown(p,mid-l+1,r-mid);//2,3参数表示左右分别有几个含在区间内
    if(a<=mid)
        awn+=Quary(a,b,2*p);
    if(b>mid)//注意这里不能加等号,不然死循环导致越界
        awn+=Quary(a,b,2*p+1);
    return awn;
}

区间更新

代码语言:javascript
复制
void updata(int a,int b,int val,int p)
{
    int l=tree[p].L;
    int r=tree[p].R;
    if(a<=l&&r<=b)//如果待修改区间比当前节点的区间大,直接修改当前节点的值,同时修改lazy的值
    {
        tree[p].sum+=val*(r-l+1);
        tree[p].lazy+=val;
        return ;
    }
    int mid=(l+r)/2;
    pushdown(p,mid-l+1,r-mid);//lazy下压
    if(a<=mid)
        updata(a,b,val,2*p);
    if(b>mid)
        updata(a,b,val,2*p+1);
    pushup(p);
}

例题

vj C – A Simple Problem with Integers 模板题

AC代码:

代码语言:javascript
复制
#include <iostream>
#include <stdio.h>
using namespace std;

const int maxn=1e5+10;

struct node
{
    int L,R;
    long long big,sum,lazy;
} tree[4*maxn];
void pushup(int p)
{
    tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;
}
void pushdown(int p,int l,int r)
{
    if(tree[p].lazy)
    {
        tree[p*2].lazy+=tree[p].lazy;
        tree[p*2+1].lazy+=tree[p].lazy;
        tree[p*2].sum+=tree[p].lazy*l;
        tree[p*2+1].sum+=tree[p].lazy*r;
        tree[p].lazy=0;
    }
}
void build(int l,int r,int p)
{
    tree[p].L=l,tree[p].R=r,tree[p].lazy=0;
    if(l==r)
    {
        scanf("%lld",&tree[p].sum);
        return ;
    }
    int mid=(l+r)/2;
    build(l,mid,2*p);
    build(mid+1,r,p*2+1);
    pushup(p);
}

long long Quary(int a,int b,int p)
{
    long long awn=0;
    int l=tree[p].L;
    int r=tree[p].R;
    if(a<=l&&r<=b)
    {
        return tree[p].sum;
    }
    int mid=(l+r)/2;
    pushdown(p,mid-l+1,r-mid);
    if(a<=mid)
        awn+=Quary(a,b,2*p);
    if(b>mid)
        awn+=Quary(a,b,2*p+1);
    return awn;
}

void updata(int a,int b,int val,int p)
{
    int l=tree[p].L;
    int r=tree[p].R;
    if(a<=l&&r<=b)
    {
        tree[p].sum+=val*(r-l+1);
        tree[p].lazy+=val;
        return ;
    }
    int mid=(l+r)/2;
    pushdown(p,mid-l+1,r-mid);
    if(a<=mid)
        updata(a,b,val,2*p);
    if(b>mid)
        updata(a,b,val,2*p+1);
    pushup(p);
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    build(1,n,1);
    int a,b,c;
    char ch;
    while(m--)
    {
        getchar();
        scanf("%c%d%d",&ch,&a,&b);
        if(ch=='Q')
            printf("%lld\n",Quary(a,b,1));
        else
        {
            scanf("%d",&c);
            updata(a,b,c,1);
        }
    }

    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-1-07 1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 定义全局变量
  • 回溯函数
  • 建树
  • 下压函数
  • 区间查询
  • 区间更新
  • 例题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档