线段树-模板

Posted waryan

tags:

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

一:线段树介绍

引例:HDU1754

注意到父亲点和左儿子,右儿子的关系,左儿子的序号是父亲的2倍,右儿子的序号是父亲的2倍+1;

 

技术图片

 

 

建树的过程如下,先建全部的左儿子然后回溯建右儿子和取区间最大值 

 

技术图片

 

 

 

 

 

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2e+5;
int n,m,a[maxn];

struct tree{
    int l,r,v;
}trees[maxn<<2];

 

1.建树

void buildtree(int s,int l,int r)
{
    trees[s].l=l,trees[s].r=r;
    if(l==r)
    {
        trees[s].v=a[l];
        return ;
    }
    int mid=l+r>>1;

    buildtree(s<<1,l,mid);//左儿子建立
    buildtree(s<<1|1,mid+1,r);//右儿子建立

    trees[s].v=max(trees[s<<1].v,trees[s<<1|1].v);//取区间最大值
}

 

2.单点修改

void update_point(int s,int a,int m)
{
    if(trees[s].l==a&&trees[s].r==a)
    {
        trees[s].v=m;
        return ;
    }
    int mid=trees[s].l+trees[s].r>>1;

    if(a<=mid)
        update_point(s<<1,a,m);//如果满足这种情况是说明这个点在左儿子的子区间
    if(a>mid)
        update_point(s<<1|1,a,m);//在右儿子的子区间

    trees[s].v=max(trees[s<<1].v,trees[s<<1|1].v);
}

 

3.单点修改

 

4.区间修改

 

5.区间查询

int ask_interval(int s,int l,int r)
{
    if(trees[s].l==l&&trees[s].r==r)
        return trees[s].v;
    int mid=trees[s].l+trees[s].r>>1;

    if(r<=mid)
        return ask_interval(s<<1,l,r);//全部在左儿子
    if(l>mid)
        return ask_interval(s<<1|1,l,r);//全部在右儿子
    if(l<=mid&&r>mid)
        return max(ask_interval(s<<1,l,mid),ask_interval(s<<1|1,mid+1,r));//左右儿子区间均有

    return 0;
}

 

 

 

 

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

线段树模板整理

线段树模板总结

线段树模板

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

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

模板 线段树(部分功能)