渣渣算法初步回顾---树状数组

本来不想写的 但最近新的算法也都学不进去 也答应了同学要写几个渣渣算法给他看 就顺便当作回溯吧。。。

算法顺序  无重要性难易之分 想到什么了又会的就写点什么

今天 我们一起来撸---树状数组

嗯 其实我是先接触了线段树 再去接触树状数组的  总体感觉 线段树应用范围比树状数组更广泛 但数组数组 更加有效率 代码也简洁 理解起来也不难 是个值得去好好掌握的算法 关于它的定义 我就做下大自然的搬运工 给出它在百度百科的定义

-------树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值。

树状数组的用法一般分2种:

1.插点问线(也是最基础的)

直接给出它的一般用到的3个函数了这里(有任何不懂得 可以参考其他大牛de博客讲解)

int lowbit(int index)
{
        return x&-x;
}
void update(int index,int num)
{
     while(index<=n)
    {
           tree[index]+=num;
           index+=lowbit(n);
     }
}
int getSum(int index)
{
	int sum=0;
	while(index>=1)
	{
		sum+=tree[index];
		index-=lowbit(index);
	}
	return sum;
}

具体解释就不给出了  今天还是想点睡了  该死的学校明天还要晨跑,关于树状数组的另一种应用 插线问点 就明天再说吧 要是状态好点 再讲讲我对树状数组的理解

悲惨的逃了思修 和辅导员在寝室邂逅…… 继续开始昨天未完成的吧

2.插线问点

其实 插线问点 与插点问线 的区别就是 区间更新与单点更新的区别 和  单点询问与区间询问的区别, 其实我们有2种写法,对应着2种不同方式的我们在main函数中的表达方式

我们先来讲第1种  3个函数完全和上面相同  这个时候我们需要更新 begin end num这3个参数 即在begin---end区间分别加上num(正负没有关系)

那么 我们就可以这样来写(这是核心步骤Key)

update(begin,num);//更新从开始点到最大值的所有节点
update(end+1,-num);//将多更新的部分 即结束点以后的所增加的全部抵消


至于查询的话 就很简单了 直接

getSum(int index)
现在再讲第2种 函数发生稍许变化的 自然main 中update的写法也将发生变化

void update(int index,int num)
{
	while(index>=1)
	{
		tree[index]+=num;
		index-=lowbit(index);
	}
}

int getSum(int index)
{
	int sum=0;
	while( index<=n )
	{
		sum++tree[index];
		index+=lowbit(index);
	}
	return sum;
}

 

update(begin-1,-num);
update(end,num);


其实 你仔细观察 会发现 这2种写法 如果我们将第二种的函数名改变一下 那么它又是相同的。。

只希望不要误人子弟 还是去看权威大牛博客 学习算法比较好

纯粹自娱自乐.......


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值