树状数组[模板]---基础

一:单点修改,区间查询

树状数组[模板]---基础_第1张图片

//单点修改,区间查询
#include
using namespace std;
using ll = long long;
vectora(5e5+5),b(5e5+5);
ll n,k;
ll lowbit(ll x)
{
	return x&(-x);
}
void add(ll x,ll y)
{
	for(ll i=x;i<=n;i+=lowbit(i))
	{
		b[i]+=y;
	}
}
void query(ll x,ll y)//前缀和相减求区间和
{
	ll sum=0;
	for(ll i=x-1;i;i-=lowbit(i))
	{
		sum-=b[i];
	}
	for(ll i=y;i;i-=lowbit(i))
	{
		sum+=b[i];
	}
	cout<>n>>k;
	for(ll i=1;i<=n;i++)
	{
		cin>>a[i];
		add(i,a[i]);//该节点与父节点及右侧2的幂的点都加上该数,利于求区间和
	}
	ll t,x,y;
	while(k--)
	{
		cin>>t>>x>>y;
		if(t==1)
		{
			add(x,y);//同理
		}
		else{
			query(x,y);//前缀和差
			//cout<>t;
	//while(t--) 
		solve();
}

二://区间修改,查询单点

树状数组[模板]---基础_第2张图片

//区间修改,查询单点
#include
using namespace std;
using ll = long long;
ll n,m;
ll c[500005],a[500005];
ll lowbit(ll x)
{
	return x&(-x);
}
void add(ll x,ll z)
{
	for(ll i=x;i<=n;i+=lowbit(i))
	{
		c[i]+=z;
	}
}
ll query(ll x)
{
	ll sum=0;
	for(ll i=x;i;i-=lowbit(i))//差分前缀和
	{
		sum+=c[i];
	}
	return sum;
}
void solve()
{
	cin>>n>>m;
	for(ll i=1;i<=n;i++)
	{
		cin>>a[i];
		add(i,a[i]-a[i-1]);//差分数组
	}
	ll t,x,y,z;
	while(m--)
	{
		cin>>t;
		if(t==1)
		{
			cin>>x>>y>>z;
			add(x,z);//原本差分数组只用修改一次,但是其含有多级父节点,故需要多次修改
			add(y+1,-z);
		}
		else{
			cin>>x;
			cout<>t;
	//while(t--) 
	solve();
	return 0;
}

三: //区间修改,区间查询

 基于二的模板,最后求的是区间的值!!

// ****n *(c[1]+c[2]+……+c[n])-(0 *c[1]+1 *c[2]+...+(n-1)*c[n])***** 
//区间修改,区间查询
#include
using namespace std;
using ll = long long;
ll n,m;
ll c[100005],a[100005],b[100005];
ll lowbit(ll x)
{
	return x&(-x);
}
///
void add(ll x,ll z)
{
	for(ll i=x;i<=n;i+=lowbit(i))
	{
		c[i]+=z;
	}
}
///
void added(ll x,ll z)
{
	for(ll i=x;i<=n;i+=lowbit(i))
	{
		b[i]+=z;
	}
}
/
ll query(ll x)
{
	ll sum=0;
	for(ll i=x;i;i-=lowbit(i))
	{
		sum+=c[i];
	}
	return sum;
}
/
ll queryed(ll x)
{
	ll sum=0;
	for(ll i=x;i;i-=lowbit(i))
	{
		sum+=b[i];
	}
	return sum;
}
/
void solve()
{
	cin>>n>>m;
	for(ll i=1;i<=n;i++)
	{
		cin>>a[i];
		add(i,a[i]-a[i-1]);//差分数组
		added(i,(i-1)*(a[i]-a[i-1]));//待减差分数组,即:(0 *c[1]+1 *c[2]+...+(n-1)*c[n]);
	}
	ll t,x,y,z;
	while(m--)
	{
		cin>>t;
		if(t==1)
		{
			cin>>x>>y>>z;
			add(x,z);//多级父节点,故需要多次修改,为了使用前缀和
			add(y+1,-z);
			added(x,z*(x-1));
			//同理:即 (0 *c[1]+1 *c[2]+...+(n-1)*c[n]);
			added(y+1,-z*(y));
		}
		else{
			cin>>x>>y;
			ll sum1=0,sum2=0;
			sum1=(x-1)*query(x-1)-queryed(x-1);//a[x-1]的前缀和
			sum2=y*query(y)-queryed(y);//a[y]的前缀和
			//即:*****n *(c[1]+c[2]+……+c[n])-(0 *c[1]+1 *c[2]+...+(n-1)*c[n])*****
			cout<>t;
	//while(t--) 
	solve();
	return 0;
}

你可能感兴趣的:(树状数组,算法,c++)