ACM_模板_线段树

线段树,作为一项统计神学,和树状数组一样也是一项需要掌握的杀手锏。

线段树的代码分为三个模块:建树·更改·查询。

1.建树:

建树的过程是通过不断的分成左子树和右子树,一层一层的叠上去。采用的是递归的思想。

void Build(int left,int right,int rt)
{
    if(left == right)
    {
         scanf("%d",&tree[rt]);
         return;
    }
    int mid = (left+right)>>1;
    Build(left,mid,rt<<1);
    Build(mid+1,right,(rt<<1)+1);
    tree[rt]=max(tree[rt<<1],tree[(rt<<1)+1]);
}

2.更改:

更改的过程是从树的最下面改的,所以在改了最下面后,我们还要一层一层的叠上去。

void Update(int p,int q,int left,int right,int rt)
{
	if(left == right)
	{
    	tree[rt]=q;
    	return;
	}
	int mid = (left+right)>>1;
	if(p <= mid)
		Update(p,q,left,mid,rt<<1);
	else 
		Update(p,q,mid+1,right,(rt<<1)+1);
	tree[rt] = max(tree[rt<<1],tree[(rt<<1)+1]);
}

3.查询:

查询才是整个线段树的核心,是成就此神学统计方法的绝学^^~,通过判断线段的左右在当前查询的线段中的位置来进行查询。

int Query(int L,int R,int left,int right,int rt)
{
    if(L<=left && right<=R)
        return tree[rt];
    int mid = (right+left)>>1;
    int ret=0;
    if(L<=mid)
        ret=max(ret,Query(L,R,left,mid,rt<<1));
    if(R>mid)
        ret=max(ret,Query(L,R,mid+1,right,(rt<<1)+1));
    return ret;
}

查询功能还可以查询一段里面的所有子树的和

int Query(int left,int right,int i)//查询
{
	int mid;
	if(b[i].left==left && b[i].right==right) return b[i].sum;
	mid = (b[i].left+b[i].right)/2;
	if(right <= mid) return Query(left,right,2*i);//在左子树
	else if(left > mid) return Query(left,right,2*i+1);//在右子树
	else return Query(left,mid,2*i)+Query(mid+1,right,2*i+1);//否则在中间
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值