数据结构(树状数组)

本文介绍了一种数据结构——树状数组,用于区间查询和单点修改的高效操作。通过二进制分解理解区间划分,详细阐述了其结构特点和维护方法,包括计算lowbit函数、getsum前缀和和add单点修改。此外,还介绍了树状数组与差分数组结合处理区间修改的应用场景和相关函数实现。
摘要由CSDN通过智能技术生成

1、树状数组是一种展开后类似树的一种数组,原理如下:

对于正整数x,我们可以将x进行二进制分解,x=2^{i_1}+2^{i_2}+...+2^{i_n},由此,我们可以将区间[1,x]划分为O(logx)个区间:

 这些区间共同的特点是,若区间结尾为R,则区间长度就等于R的二进制分解下最小次幂,即为lowbit(R),例如7=2^2+2^1+2^0,区间[1,7]可以分为[7,7]、[5,6]、[1,4],长度分别是lowbit(7)=1、lowbit(7-lowbit(7))=2、lowbit(6-lowbit(6))=4,因此,只要给定x,我就可以算出[1,x]所分成的O(logx)个小区间

由此,对于给定的一个数组a,我们建立一个数组c,其中c[x]保存序列a的区间[x-lowbit(x)+1,x]中所有数的和,对于这个数组c,可以看成一个树形结构,该结构满足如下性质:

(1)、每个内部节点c[x]保存以它为根的子树中所有叶节点的和

(2)、每个内部节点c[x]的子节点个数等于lowbit(x)的位数

(3)、除根节点外,每个内部节点c[x]的父节点是c[x+lowbit(x)]

(4)、树的深度为O(logn)

树状数组支持的基本操作有两个,一个是单点修改,另一个是查询区间和

2、区间查询,单点修改,可以直接用原数组进行树状数组维护

//区间查询
int a[maxn], c[maxn];
ll lowbit(ll x)
{
	return x & (-x);
}
ll getsum(int x)        //获取前缀和
{
	ll sum = 0;
	for (; x; x -= lowbit(x))     //遍历c[x]划分成的每个小区间
		sum += c[x];
	return sum;
}
void add(int x, int y)
{
	for (; x <= n; x += lowbit(x))     //由叶子节点不断向上
		c[x] += y;
}

add(i, x);    //i位置加上x

3、树状数组+差分数组:如果需要区间修改,那么则需要用树状数组维护差分数组,因为当对区间值进行加减时,对差分数组只有两端的数在改变

//树状数组+差分数组
ll b[maxn], c[maxn], n;
ll lowbit(ll x)
{
	return x & (-x);
}
void addone(int x, ll y)			//x下标,y数值
{
	ll z = x * y;
	for (; x <= n; x += lowbit(x))
	{
		c[x] += y;
		b[x] += z;    //如果需要区间查询(前缀和),需要额外维护一个x*c[x]的树状数组
	}
}
void addall(int l, int r, ll y)
{
	addone(l, y);
	addone(r + 1, -y);
}
ll getsum(int x)			//前缀和
{
	ll sum1 = 0, sum2 = 0;
	for (; x; x -= lowbit(x))
	{
		sum1 += c[x];
		sum2 += b[x];
	}
	return sum1 * (x + 1) - sum2;
}
ll query(int l, int r)		//求指定区间和
{
	return getsum(r) - getsum(l - 1);
}
void solve()
{
	int m;
	ll x, y = 0;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> x;
		addone(i, x - y);
		y = x;
	}

	addall(l, r, x);        //区间修改

    cout << query(l, r) << '\n';        //区间查询

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值