线段树模板

Posted walfy

tags:

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

自己写的模板,方便以后查看

求最大值的:

#include<iostream>
#include<cstdio>
using namespace std;
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
const int maxn=222222;
int value[maxn<<2];
void PushUp(int rt)
{
    value[rt]=max(value[rt<<1],value[rt<<1|1]);
}
void btree(int l,int r,int rt)
{    //初始为(1,n,1) 
    if(l==r)
    {
        scanf("%d",&value[rt]);
        return ;
    } 
    int m=(l+r)>>1;
    btree(ls);
    btree(rs);
    PushUp(rt);
}
void update(int x,int v,int l,int r,int rt)
{    //初始化为(a,b,1,n,1) 
    if(l==r)
    {
        value[rt]=v;
        return ;
    }
    int m=(l+r)>>1;
    if(x<=m)update(x,v,ls);
    else update(x,v,rs);
    PushUp(rt);
}
int query(int L,int R,int l,int r,int rt)
{    //初始化为(a,b,1,n,1) 
    if(L<=l&&r<=R)return value[rt];
    int m=(l+r)>>1,ans=0;
    if(L<=m)ans=max(ans,query(L,R,ls));
    if(R>m)ans=max(ans,query(L,R,rs));
    return ans;
}
int main()
{
}

求区间和:

#include<iostream>
#include<cstdio>
using namespace std;
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
const int maxn=50005;
int value[maxn<<2],ans;
void PushUp(int rt)
{
    value[rt]=value[rt<<1]+value[rt<<1|1];
}
void btree(int l,int r,int rt)
{    //初始为(1,n,1) 
    if(l==r)
    {
        scanf("%d",&value[rt]);
        return ;
    } 
    int m=(l+r)>>1;
    btree(ls);
    btree(rs);
    PushUp(rt);
}
void update(int x,int v,int l,int r,int rt)
{    //初始化为(a,b,1,n,1) 
    if(l==r)
    {
        value[rt]+=v;
        return ;
    }
    int m=(l+r)>>1;
    if(x<=m)update(x,v,ls);
    else update(x,v,rs);
    PushUp(rt);
}
void query(int L,int R,int l,int r,int rt)
{    //初始化为(a,b,1,n,1) 
    if(L<=l&&r<=R)
    {
        ans+=value[rt];
        return ;
    }
    if(l==r)return; 
    int m=(l+r)>>1;
    if(R<=m)query(L,R,ls);
    else if(L>m)query(L,R,rs);
         else
         {
             query(L,R,ls);
             query(L,R,rs);
          } 
           
}
int main()
{
    return 0;
}

区间更新的:

#include<iostream>
#include<cstdio> 
using namespace std;
#define ll long long
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
const int maxn=100005; 
ll value[maxn<<2],add[maxn<<2];
void PushUp(int rt)
{
    value[rt]=value[rt<<1]+value[rt<<1|1];
}
void PushDown(int rt,int m)//m是当前节点区间的范围  
{          //例如1-5  右儿子4-5,左儿子1-3  m=5,m>>1=2刚好是右儿子区间范围,m-(m>>1)=3为左儿子区间范围
    if(add[rt])//向下更新子节点 
    {
        add[rt<<1]+=add[rt];//更新左儿子的lazy标记
        add[rt<<1|1]+=add[rt];//右儿子
        value[rt<<1]+=(m-(m>>1))*add[rt];//更新左儿子的权值,应该乘上左儿子区间(r-l+1)
        value[rt<<1|1]+=(m>>1)*add[rt];//应该乘右儿子区间范围
        add[rt]=0;
    }
}
void btree(int l,int r,int rt)
{   //初始化1,n,1 
    add[rt]=0;
    if(l==r)
    {
        scanf("%lld",&value[rt]);
        return ;
    }
    int m=(l+r)>>1;
    btree(ls);
    btree(rs);
    PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt)
{    //初始化a,b,c,1,n,1 
    if(L<=l&&r<=R)//给定区间大于现有区间 
    {
        add[rt]+=c;//标记加上 
        value[rt]+=(ll)c*(r-l+1);//更新当前节点 
        return ;
    }
    PushDown(rt,r-l+1);//向下更新子节点因为下一步要使用子节点 
    int m=(l+r)>>1;
    if(L<=m)update(L,R,c,ls);
    if(R>m)update(L,R,c,rs);
    PushUp(rt);//向上关系父节点 
} 
ll query(int L,int R,int l,int r,int rt)
{   //初始化为a,b,1,n,1 
    if(L<=l&&r<=R)return value[rt];
    PushDown(rt,r-l+1);
    int m=(l+r)>>1;
    ll ans=0;
    if(L<=m)ans+=query(L,R,ls);
    if(R>m)ans+=query(L,R,rs);
    return ans;
}
int main()
{
}

 

以上是关于线段树模板的主要内容,如果未能解决你的问题,请参考以下文章

线段树模板整理

线段树模板总结

线段树模板

模板线段树-单点修改,区间查询

P3834 模板可持久化线段树 1(主席树)

模板 线段树(部分功能)