树状数组

树状数组的本质是将前缀进行拆分维护,\(i\)号节点维护的是原序列上\([i-lowbit(i)+1,i]\)这段区间的信息。

\(lowbit(x)\)表示\(x\)这个数在2进制下从低到高第一个非零位在十进制下的,例如\(lowbit(7)=1,lowbit(8)=8\)

根据计算机补码的性质可得\(lowbit(x)=x\)&\((-x)\)

单点修改:其实就是一个不断找到管辖自己区间的过程,方法就是不断给i自己加上\(lowbit(i)\)跳到下一个管辖自己的区间。

前缀查询:就是把前缀进行拆分,方法就是不断给\(i\)自己扣除\(lowbit(i)\)跳到下一个前缀。

这两个操作的复杂度都是单次\(O(log\) \(n)\)的。

\(code\)

void update(int t,int v)
{
	while(t<=n)
	{
		tree[t]+=v;
		t+=lowbit(t);
	}
}
int query(int t)
{
	int sum=0;
	while(t)
	{
		sum+=tree[t];
		t-=lowbit(t);
	}
	return sum;
}

......

update(x,y);//单点修改,x加上y
query(y)-query(x-1)//区间查询,x到y的和

树状数组还可求逆序对

posted @ 2020-01-22 19:52  lhm_liu  阅读(124)  评论(0编辑  收藏  举报