算法:树状数组

3 阅读1分钟

树状数组

视频讲解

1.计算长度

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

2.计算前x项和

int query(int x)
{
	int ret = 0;
	while(x)
	{
		ret += c[x];
		x = x -lowbit(x);
	}
	return ret;
}

实现在第x数上加上val

void add_x(int x,int val)
{
  while(x <= n)
  {
    c[x] += val;
    x = x +lowbit(x);
  }
}

例题 :树状数组

题解:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 5e5+5;
ll C[N];
ll n,m;
ll x,y,k;
ll lowbit(ll x)
{
	return x & (-x);
}
ll query(ll x)
{
	ll res = 0;
	while(x)
	{
		res +=C[x];
		x = x-lowbit(x);
	}
	return res;
}
void add_x(ll x,ll val)
{
	while(x <= n)
	{
		C[x] += val;
		x = x + lowbit(x);
	}
}

int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int xx;
		cin>>xx;
		add_x(i,xx);
	}
	for(int i=1;i<=m;i++)
	{
		cin>>k>>x>>y;
		if(k==1)
		{
			add_x(x,y);
		}
		if(k==2)
		{
			ll l,r;
			l=query(x-1);
			r=query(y);
			cout<<r-l<<"\n";
		}
	}
	
}

例题:P3368 树状数组2 (差分+树状数组)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N =500005;
ll n,m,k;
ll c[N];
ll lowbit(ll x)
{
	return x & (-x);
}
ll query(ll x)
{
	ll res=0;
	while(x)
	{
		res += c[x];
		x -= lowbit(x);
	}	
	return res;
}
void add_x(ll x,ll val)
{
	while(x <= n)
	{
		c[x] += val;
		x += lowbit(x);	
	}	
	
}
int main()
{
	cin>>n>>m;
	ll now=0;;
	ll a;
	for(int i=1;i<=n;i++)
	{
		cin>>a;
		add_x(i,a-now);//差分 
		now = a;//这里的now相当于上一个a 
	}
	for(int i=1;i<=m;i++)
	{
		cin >> k ;
		if(k==1)
		{
			ll x,y,z;
			cin>>x>>y>>z;
			add_x(x,z);//差分 
			add_x(y+1,-z);//差分 
		}
		else if(k==2)
		{
			ll t;
			cin>>t;
			cout<<query(t)<<endl;
		}
	}
	return 0;
}