线段树超级大模版

Posted smallhester

tags:

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

建树

void build(int o,int l,int r)   //o:当前建立的节点 l:左端点  r:右端点
{
    if(l == r)                  //建立叶子信息
        st[o] = a[l];
    else
    {
        int m = l + ((r-l) >> 1);   // m 为中间点,左儿子结点为 [l,m] ,右儿子结点为 [m+1,r];
        build(o << 1,l,m);          //构建左儿子结点
        build((o<<1)|1,m+1,r);      //构建右儿子结点
        st[o] = max(st[o << 1],st[(o<<1)|1]);   //递归返回时用儿子结点更新父节点,此处可进行更新最大值、最小值、区间和等操作
    }
}


 build(1, 1, n);//主函数里的语句

 

 单点修改

void update(int o,int l,int r,int ind,int ans)  //o、l、r为当前更新到的结点、左右端点,ind为需要修改的叶子结点左端点,ans为需要修改成的值;
{
    if(l == r)      //若当前更新点的左右端点相等即到叶子结点时,直接更新信息并返回
    {
        st[o] = ans;
        return ;
    }
    int m = l + ((r-l) >> 1);
    if(ind <= m)
        update(o << 1,l,m,ind,ans);
    else
        update((o<<1)|1,m+1,r,ind,ans);
    st[o] = max(st[o<<1],st[(o<<1)|1]);     //递归回之后用儿子结点更新父节点(此处是区间最大值)也可以是最小值或者是区间和
}


 update(1, 1, n, a, b);//在主函数里的语句

 

区间查询

int query(int o,int l,int r,int ql,int qr)      //ql、qr为需要查询的区间左右端点
{
    if(ql > r || qr < l)    //若当前结点和需要查找的区间不相交,则返回一个对于区间查询无关的值(如求和时返回0,求最大值时返回-1等)
        return -1;
    if(ql <=l && qr >=r)    //若当前结点的区间被需要查询的区间覆盖,则返回当前结点的信息
        return st[o];
    int m = l + ((r-l) >> 1);
    int p1 = query(o<<1,l,m,ql,qr);     //p1为查询左儿子结点得到的信息,p2为查询右儿子结点得到的信息
    int p2 = query((o<<1)|1,m+1,r,ql,qr);
    return max(p1,p2);      //综合两个儿子结点的信息并返回
}


query(1, 1, n, a, b)//主函数里的查询语句

 

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

吊打线段树的超级树状数组

模版:线段树

Multiset (权值线段树模版)

线段树模版(转)

线段树常用技巧模版(刷题篇)

线段树常用技巧模版(刷题篇)