基础线段树(建树,查询,单点更新)

线段树就是讲一连串的数字转换成树的形式,有利于对数据进行操作,效率较高

下面是建树操作

 

 1 void build(int l,int r,int i)//左节点 l  右节点  r  当前节点 i
 2 {
 3     if(l==r)//找到节点 存入数据
 4     {
 5         scanf("%d",&sum[i]);
 6         return ;
 7     }
 8     int m=(l+r)>>1,ls=i<<1,rs=ls|1;//  m 为中点 ls 为左儿子 rs 为右节点
 9     build(l,m,ls);//建立左子树
10     build(m+1,r,rs);//建立右子树
11     pushup(i); //更新父节点 自定义函数
12 }

 

下面是线段树查询操作代码

查询操作根据不同的题目有不同的写法(其实基本上都是相同的,只是有一点不同)

 

int query(int L,int R,int l,int r,int i)// 查询的区间(L,R)  起始区间(l,r) 当前节点  i
{
    if(L<=l&&r<=R)//所要查找的区间包含所有节点
    {
        return sum[i];
    }
    int m=(l+r)>>1,ls=i<<1,rs=ls|1;
    int ans=0;
    if(L<=m)
        ans+=query(L,R,l,m,ls);//求和
/*sum[i]=max(sum[i<<1],sum[i<<1|1];
求最值*/
if(R>m)
        ans+=query(L,R,m+1,r,rs);
/*sum[i]=max(sum[i<<1],sum[i<<1|1];
求最值*/
return ans; }

接下来是单点更新

在线段树中找到特定的一个节点, 对其数值进行更新

void update(int k,int v,int l,int r,int i)//需要更新的节点 k 更新后的数值 v  起始区间(l,r) 当前节点 i
{
    if(l==r)//找到指定的节点
    {
        sum[i]+=v;//对数值进行更新 此句依题意写
        return ;
    }
    int m=(l+r)>>1,ls=i<<1,rs=ls|1;
    //下面是递归操作,细细琢磨,有点二分的味道
    if(k<=m)
        update(k,v,l,m,ls);
    else
        update(k,v,m+1,r,rs);
    pushup(i);//更新父节点
}

https://blog.csdn.net/yitongjun/article/details/53193724

上面这个链接的博客关于线段的 写的很全面 

 ps:第一次写,不喜勿喷

  

posted on 2018-03-25 18:14  言殇  阅读(100)  评论(0)    收藏  举报