线段树学习(一)

感谢兴海同学的耐心解释。可怜

今天把线段树的创建,更新(插入),查找操作熟悉了。以前其实看过类似的资料,不过那时候脑子一片浆糊= =。。

想画图来着,感觉太不给力了。

直接说得了。


一、建图

我感觉,线段树的建图有两种。

1、最后一层建成线段,就是所有区间都是开区间,最后一层是[1,2]  [2,3] [3,4]什么的。

2、最后一层建成点,类似[1,1]  [2,2]..


今天建了下,个人比较喜欢第一种建法~感觉正好就是线段嘛。

建树我用的数组模拟邻接表,本来是想用指针的,不过感觉挺麻烦的,如果用指针的话就不能用位运算了哈。建树很简单,线段树是递归定义的,所以建树也是递归就好。

树的左右孩子直接由数组下标去寻找,左孩子是2*x,右孩子是2*x+1

#define L(x) x << 1
#define R(x) x << 1 | 1

根据题目的不同,树的结点可以增加其他的值去标记一些东西。比如我今天过的两个题,是标记颜色值,或者是否覆盖的。

void Build(int t,int l,int r)
{
	node[t].cover = 0;
	node[t].l = l;
	node[t].r = r;
	if( l == r-1 )	return ;
	int mid = (l+r)>>1;
	Build(L(t),     l,	   mid);
	Build(R(t),   mid,       r);
}

二、更新(我更喜欢叫更新是Updata。。。虽然准确的说应该是Update。。。)

1、注意更新父节点对子节点的影响。

2、注意更新子节点对父节点的影响。

3、开始我一直拿初始的l 和 r去更新,根本没用用到mid。后来问兴海,他说有的时候会有用。想了下,如果跟覆盖的区间有关的话,应该还是得用到,不过这两题都没用到 = =。。

4、如果父节点已经被覆盖过的话,如果这个父节点的子节点需要覆盖其他的颜色的话,父节点的颜色需要往子节点传递,才能保证这个线段不被多个颜色覆盖。传递后,这个父节点颜色就没有了,标记成-1。

void Updata(int t,int l,int r,int col)
{
	if( r <= l ) return ;
	if( l <= node[t].l && node[t].r <= r ) 
	{
		node[t].cover = col;
		return ;
	}
	int mid = (node[t].l + node[t].r) >> 1; 
	if( node[t].cover > 0 )
	{
		node[R(t)].cover = node[t].cover;
		node[L(t)].cover = node[t].cover;
		node[t].cover = -1;
	}
	if( l >= mid )
		Updata( R(t), l, r, col);
	else
		if( r <= mid )
			Updata( L(t), l, r, col);
		else
		{
			Updata( L(t),   l, mid, col);
			Updata( R(t), mid,   r, col);
		}
}
(剩下的见下一篇吧,睡觉去,明早得早起)




评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值