“一/二维树状数组:区/单间修改,区/单间查询”题解(树状数组例题)

本蒟蒻是一个萌新,希望支持。

一维树状数组 1 :单点修改,区间查询

见本蒟蒻的博客

一维树状数组 2 :区间修改,单点查询

【模板】树状数组 2(洛谷)
树状数组 2 :区间修改,单点查询(Liuser’s OJ)

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  1. 将某区间每一个数数加上 x;
  2. 求出某一个数的值。

输入格式

第一行包含两个整数 N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含 N 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值。
接下来 M 行每行包含 2 或 4个整数,表示一个操作,具体如下:

  1. 含义:将区间 [x,y] 内每个数加上 k;
1 x y k
  1. 含义:输出第 xxx 个数的值。
2 x

输出格式

输出包含若干行整数,即为所有操作 2 的结果。

样例

样例1输入
5 5
1 5 4 2 3
1 2 4 2
2 3
1 1 5 -1
1 3 5 7
2 4
样例1输出
6
10

AC代码+注释

#include
using namespace std;

long long a[1000005],BIT[1000005],n,q,s=0,t,l,r,z;

long long Lowbit(long long x)
{
	return x&-x;
}

long long Sum(long long x)
{
	long long ans=0;
	for(long long i=x;i;i-=Lowbit(i))
	{
		ans+=BIT[i];
	}
	return ans;
}

void Add(long long x,long long y)
{
	while(x<=n)
	{
		BIT[x]+=y;
		x+=Lowbit(x);
	}
}

int main()
{
	scanf("%lld%lld",&n,&q);
	for(long long i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		Add(i,a[i]-s);
		s=a[i];
	}
	for(long long i=0;i<q;i++)
	{
		scanf("%lld",&t);
		if(t==1)
		{
			scanf("%lld%lld%lld",&l,&r,&z);
			Add(l,z);
			Add(r+1,-z);
		}
		else
		{
			scanf("%lld",&l);
			printf("%lld\n",Sum(l));
		}
	}
	return 0;
}

一维树状数组 3 :区间修改,区间查询

树状数组 3 :区间修改,区间查询(Liuser’s OJ)

AC代码+注释

#include
using namespace std;

long long n,q,a[1000005],BIT1[1000005],BIT2[1000005],t,l,r,x;

long long Lowbit(long long x)
{
	return x&-x;
}

void Update(long long x,long long y)
{
	for(long long i=x;i<=n;i+=Lowbit(i))
	{
		BIT1[i]+=y;
		BIT2[i]+=(long long)(x-1)*y;
	}
}

long long Sum(long long x)
{
	long long ans=0;
	for(long long i=x;i;i-=Lowbit(i))
	{
		ans+=BIT1[i]*x-BIT2[i];
	}
	return ans;
}

int main()
{
	scanf("%lld%lld",&n,&q);
	for(long long i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		Update(i,a[i]-a[i-1]);
	}
	for(long long i=1;i<=q;i++)
	{
		scanf("%lld%lld%lld",&t,&l,&r);
		if(t==1)
		{
			scanf("%lld",&x);
			Update(l,x);
			Update(r+1,-x);
		}
		else
		{
			printf("%lld\n",Sum(r)-Sum(l-1));
		}
	}
	return 0;
}

二维树状数组 1:单点修改,区间查询

二维树状数组 1:单点修改,区间查询(Liuser’s OJ)

AC代码+注释

#include
using namespace std;

long long BIT[10005][10005],n,m,flag,a,b,c,d;

long long Lowbit(long long x)
{
	return x&(-x);
}

void Update(long long x,long long y,long long z)
{
	for(long long i=x;i<=n;i+=Lowbit(i))
	{
		for(long long j=y;j<=m;j+=Lowbit(j))
		{
			BIT[i][j]+=z;
		}
	}
}

long long Sum(long long x,long long y)
{
	long long ans=0;
	for(long long i=x;i>0;i-=Lowbit(i))
	{
		for(long long j=y;j>0;j-=Lowbit(j))
		{
			ans+=BIT[i][j];
		}
	}
	return ans;
}

int main()
{
	scanf("%lld%lld",&n,&m);
	while(scanf("%lld",&flag)!=EOF)
	{
		scanf("%lld%lld%lld",&a,&b,&c);
		if(flag==1)
		{
			Update(a,b,c);
		}
		else
		{
			scanf("%lld",&d);
			printf("%lld\n",Sum(c,d)+Sum(a-1,b-1)-Sum(a-1,d)-Sum(c,b-1));
		}
	}
	return 0;
}

二维树状数组 2:区间修改,区间查询

二维树状数组 3:区间修改,区间查询(Liuser’s OJ)

#include
using namespace std;

long long s[2050][2050],ss[2050][2050],sss[2050][2050],ssss[2050][2050],n,m,flag,a,b,c,d,e;

long long Lowbit(long long x)
{
	return x&-x;
}

void Update(long long x,long long y,long long z)
{
	for(long long i=x;i<=n;i+=Lowbit(i))
	{
		for(long long j=y;j<=n;j+=Lowbit(j))
		{
			s[i][j]+=z;
			ss[i][j]+=x*z;
			sss[i][j]+=y*z;
			ssss[i][j]+=x*y*z;
		}
	}
	return ;
}

long long Sum(long long x,long long y)
{
	long long sum=0;
	for(long long i=x;i;i-=Lowbit(i))
	{
		for(long long j=y;j;j-=Lowbit(j))
		{
			sum+=(x+1)*(y+1)*s[i][j]-(y+1)*ss[i][j]-(x+1)*sss[i][j]+ssss[i][j];
		}
	}
	return sum;
}

int main()
{
	scanf("%lld%lld",&n,&m);
	memset(s,0,sizeof(s));
	memset(ss,0,sizeof(ss));
	memset(sss,0,sizeof(sss));
	memset(ssss,0,sizeof(ssss));
	while(scanf("%lld",&flag)!=EOF)
	{
		scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
		if(flag==1)
		{
			scanf("%lld",&e);
			Update(a,b,e);
			Update(c+1,b,-e);
			Update(a,d+1,-e);
			Update(c+1,d+1,e);
		}
		else
		{
			printf("%lld\n",Sum(c,d)-Sum(a-1,d)-Sum(c,b-1)+Sum(a-1,b-1));
		}
	}
	return 0;
}

你可能感兴趣的:(树状数组)