您的位置:首页 > 理论基础 > 数据结构算法

线段树

2015-12-10 00:01 274 查看
线段树对于Laxy还是消化了一晚上,才想明白,之前想错了,只希望能学到点,积累点。

query代表查询,build代表建树,updata代表更新,push_down就是laxy,应该是精华的地方吧。



#include<cstdio>
#include<iostream>
#include<vector>     //包括max函数
using namespace std;
int tree[20];
int num[10] = {0, 1, 3, 2, 5, 4, 8};
int add[20];
int n=1;


对于线段树求最大值和最小值,要主要返回时的值,下面标注出来了

int  build(int L,int R,int rx)     //求最大值
{
if( L == R) return tree[rx]=num[L];
return tree[rx]=max(build( L, (L + R )/2,rx*2),build( (L + R)/2+1, R ,rx*2+1 ));
}
int query(int l, int  r,int L,int R,int rx)
{
if( l > R || r < L)  return -0x7ffffff; //如果不在这个区间,就要返回最小的,确保得到最大的
if( l <= L &&  r >=R) return tree[rx];
return max(query( l , r, L ,(L + R)/2,rx*2) ,query( l, r , ( L +R)/2+1, R,rx*2+1));
}


求和,要注意不需要的地方返回0

int build(int L,int R,int rx)    //求和的最大值
{
if( L == R) return tree[rx]=num[L];
return tree[rx]=sum(build( L, (L+R)/2,rx*2),build( (L+R)/2+1,R,rx*2+1));
}
int query( int l, int r,int L,int R,int rx)
{
if( l > R || r < L) return 0;     //求和不在区间就返回0
if( l <= L && r>= R ) return tree[rx];
return tree[rx]=sum(query(l,r,L,(L+R)/2,rx*2),query(l,r,(L+R)/2+1,R,rx*2+1));
}


最后是更新区间,Laxy操作的地方

int build(int L,int R,int rx)       //下面是区间的更新
{
if( L == R) return tree[rx]=num[L];
return tree[rx]=sum(build( L, (L+R)/2,rx*2),build( (L+R)/2+1,R,rx*2+1));
}
int updata(int l,int r,int L,int R,int rx)     //更新
{
if ( l > R || r < L) return tree[rx];
if ( l <= L && r >=R )
add[rx]=n*(R-L+1);
return tree[rx] += add[rx];
//这个地方找到了应该就去更行它的子节点,但是没有,这就是Laxy操作,直接返回
//到用的时候在去更新,看 push_down函数
}
return tree[rx]=sum(updata(l,r,L,(L+R)/2,rx*2),updata(l,r,(L+R)/2+1,R,rx*2+1));
}
void push_down(int rx,int L,int R)            //Laxy操作
{
if( L == R) return ;  //如果是叶子节点,无左右孩子所以直接返回
add[rx*2] += ((L+R)/2-L+1)*n;       //更新左右的子节点
tree[rx*2] += add[rx*2];
add[rx*2+1] += ( R- (L+R)/2-1+1) *n;
tree[rx*2+1] += add[rx*2+1];
}
int query( int l, int r,int L,int R,int rx)     //查询函数
{
if( l > R || r < L) return 0;
if( add[rx] != 0)       //如果查找的这个区间包括应该更新而未更新的节点,就要去调用push_down 让其更新
{
push_down(rx,L,R);
add[rx]=0;
}
if( l <= L && r>= R ) return tree[rx];
return sum(query(l,r,L,(L+R)/2,rx*2),query(l,r,(L+R)/2+1,R,rx*2+1));
}


主函数

int main()
{
build(1,6,1);
updata(2,5,1,6,1);
for( int i = 0 ; i < 20; i ++ )        printf("%d ",tree[i]);

putchar('\n');
printf("%d" ,query(2,3,1,6,1));
return 0;
}


希望没有错误,可能还是理解的不透彻,说不明白,做不来。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树 数据结构 ACM