学习数组数组的好处:
树状数组相对于线段树的编码来讲,树状数组的编码并不复杂,反而很简单,对于一些区间求和,区间求最大值,维护区间的问题,反而能更简单的解决
树状数组核心代码:
int lowbit(int i)//lowbit()可以寻找树状数组中的前向位置和后向位置
{
return i&(-i);
}
例如要更改一个区间当中的和
void update(int i,int k)//i代表位置,k代表更改量
{
//由于更改k只影响i--n的结果所以
while(i<=n)
{
c[i]+=k;
i+=lowbit(i);
}
}
假如要求一段区间的和我
int getsum(int i)//这里先求1---i的和
{
int res=0;
while(i>0)
{
res+=c[i];
i-=lowbit(i);
}
}
完整求和代码:
#include
using namespace std;
#define maxn 1005
int a[maxn],c[maxn];
int n;//n个节点
int lowbit(int x)
{
return x&(-x);
}
void update(int i,int k)//每次在i位置上+k,故i上的所有和更新
{
while(i<=n)
{
c[i]+=k;
i+=lowbit(i);
}
}
int getsum(int i)//求1--i的和
{
int res=0;
while(i>0)
{
res+=c[i];
i-=lowbit(i);
}
return res;
}
int main()
{
memset(c,0,sizeof(c));
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
update(i,a[i]);//从后往前更新
}
int m;
scanf("%d",&m);
while(m--)
{
int i,j;
scanf("%d %d",&i,&j);
int sum=getsum(j)-getsum(i-1);
printf("%d\n",sum);
}
}
}
如果我们要修改[l,r]
区间的值,我们只需要update(l,k),
修改l
的父辈,然后在update(r+1,-k)把之前的父辈的值修改回来,区间修改就已经完成了
void update(int i,int k)//在i位置,添加k
{
while(i<=n)
{
c[i]+=k;
//printf("%d\n",i);
i+=lowbit(i);
}
}
update(l,k);
update(r+1,-k);
注意:
在否循环里输入每个节点的值,经过update()
,每个点的值就会改为我们操作想要的值
int getpoint(int i)//单点查询
{
int res=0;
while(i>0)
{
res+=c[i];
//printf("%d\n",i);
i-=lowbit(i);
}
return res;
}//该操作即可完成单点查询,单点查询的查询的值主要update()
的操作
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int Maxn = 2e5+10;
int a[Maxn], h[Maxn], n; // a[] 数列的值,h[] 区间最大值
void add (int x, int val)
{
while (x <= n)
{
h[x] = max (h[x], val);
x += x&(-x);
}
}
int query (int L, int R)
{
int ret = 0, len = R-L+1;
while (len && R) // len 是当前还需要判断的范围长度,R是对应区间最大值的下标
{
if (len < (R&(-R)))
{
ret = max (ret, a[R]);
R--;
len--;
}
else
{
ret = max (ret, h[R]);
len -= (R&(-R)); // 不断的缩短要判断的区间长度
R -= (R&(-R));
}
}
return ret;
}
int main (void)
{
int m;
while (scanf ("%d%d", &n, &m) != EOF)
{
memset (h, 0, sizeof (h));
for (int i = 1; i <= n; ++i)
{
scanf ("%d", &a[i]);
add (i, a[i]);
}
char op[2], b[10];
int x, y;
while (m--)
{
scanf ("%s%d%d", op, &x, &y);
gets (b);
if (!strcmp (op, "U"))
{
a[x] = y;
add (x, y);
}
else
{
printf ("%d\n", query (x, y));
}
}
}
return 0;
}