树状数组&&线段树

本文深入探讨了树状数组和线段树这两种高效数据结构,详细讲解了它们的实现原理,包括lowbit技巧、修改操作和查询操作。同时,通过实例展示了线段树在解决区间查询和修改问题上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

树状数组

树状数组就是一个可以是一个查询和修改复杂度都为log(n)的数据结构。为很多的查询和修改的速度提高了,减少的复杂度。
首先,我感觉很多人对这个的第一个理解肯定是树状应该是相互包含的一个样子,事实也是这样的。然后我看了很多的视频进行理解这个到底是什么样的东西,确实最后感觉有点像排列组合都是由规律的东西,而且很多公式只要记住好像就可以进行运用。

lowbit

int lowbit(int n)
{
  return n&(-n);
  }

这个就是找到二进制中最后一个1的位置
很多博客主都进行就讲解这个为什么是这样,然后进行理解一下就是。
10100 ——反码——01011——再在这个基础上加1——01100 取反末尾加1
注意:lowbit(0)=0,死循环。

修改:

对某个元素进行加法操作

void update(int x,int y)
{
		for(;x<=N;x+=lowbit(x))
		c[x]+=y;}

扩展

常用的代码:

int update(int x,int y,){
		int i=x,res=0while(i>0)
		{ int j=y;
		while(j>0)
		{
			res+=c[i][j]
			j-=lowbit(j);
			    }
		i-=lowbit(i);
			}
	return res;
		}
int update(int x,int y,int z){
		int i=x;
		while(i<=n)
		{
		while(j<=m)
		{
			c[i][j]+=z;
			j+=lowbit(j);
			}
		i+=lowbit(i);
			}}

查询:

查询前缀的和

int sum(int x)
{
		int ans=0;
		for(;x=-lowbit(x)) ans+=c[x];
		return ans;
		}

统计a[x]…a[y]的和

在查询和的基础上最后调用sum的操作sum(y)-sum(x-1)

线段树

看了很多视频,都说只要是树状数组可以解决的线段树都可以解决,然后相比加来看线段树当然复杂一点。

在这里插入图片描述
看这个图片就很明显了,就是把一个个区间分成一个个小块,最后分到一个最具体的。所以首先最重要的就是找到左右的两个端点,才可以进行分。

初始建树(就是找 到范围左右点)

代码:

void bulid(int k,int l,int r)   //k表示当前结点的编号
{
	if(l==r)    //l左结点,r右结点
	{
	mi[k]=v;    //对应区间的最小值为原序列中的对应值
	return;
	}
	int mid=(l+r)/2;
	bulid(k*2,l,mid);   //左子树
	bulid(k*2+l,mid+1,r);    //右子树
	mi[k]=min(mi[k*2],mi[k*2+1]);   //自下向上更新
	}

询问:

区间进行询问操作

代码:

int query_min(int k,int l,int r,int x,int y)//x,y为询问区间,l,r为当前区间
{
	if(y<1||x>r) return ‘极大值’;
	if(x<=1&&r<=y) return mi[k];//询问区间在当前区间,返回一个极大值
	int mid=(l+r)/2;
	return min(query_min(k*2,l,mid,x,y),query_min(k*2+1,mid+1,r,x,y));
	}//否者分别处理左子区间和右子区间

修改:

单点修改:

void change(int k,int l,int r,int x,int v)//x为原序列位置,v为要改变的值
{
	if(r<x||l>x) return ;
	if(l==r&&l==x)
	{
	mi[k]=v;
	return ;
	}
	int mid(l+r)/2;
	change(k*2+1,mid+1,r,x,v);
	change(k*2,l,mid,x,v);
	mi[k]=min(mi[k*2],min[k2+1]);
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值