hdu 1556 Color the ball(树状数组)

时间:2023-03-09 16:01:58
hdu 1556 Color the ball(树状数组)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556

题意:N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数[a,b]之间的气球染一次色,最后问每个气球染了多少种颜色。

分析:这是树状数组的第二种应用,区间成段更新,然后求某点的值。

update(x,num)表示x位置的值增加num,sum(x)表示求1到x的和。

更新[l,r]区间时,

先update(l,k),然后update(r+1,-k),就会导致sum(l)到sum(r)的值均增加了k,然后[1,l)和(r,max)这两个范围内的sum都不变,这样sum(x)就是x这个点当前的值了。

在纸上自己画一画,模拟一下就能明白了。

AC代码如下:

 #include<stdio.h>
#include<string.h>
#define N 100010
int d[N],n;
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int num)
{
while(x<=n)
{
d[x]+=num;
x+=lowbit(x);
}
}
int GetSum(int x)
{
int s=;
while(x>)
{
s+=d[x];
x-=lowbit(x);
}
return s;
}
int main()
{
int i,a,b;
while(scanf("%d",&n)&&n)
{
memset(d,,sizeof(d));
for(i=;i<n;i++)
{
scanf("%d%d",&a,&b);
update(a,);
update(b+,-);
}
for(i=;i<n;i++)
printf("%d ",GetSum(i));
printf("%d\n",GetSum(n));
}
return ;
}

上面的方法是树状数组最基本的向上修改,向下统计的形式,其实还可以向上统计,向下修改。

树状数组中的每个节点都代表了一段线段区间,每次更新的时候,根据树状数组的特性可以把b以前包含的所有区间都找出来,然后把b以前的

区间全部加一次染色次数。然后,再把a以前的区间全部减一次染色次数,这样就修改了树状数组中的[a,b]的区间染色次数,查询每一个点总的染色次

数的时候,就可以直接向上统计每个父节点的值,就是包含这个点的所有区间被染色次数,这就是树状数组中向下查询,向上统计的典型应用

这样的话update()和sum()的代码就需要修改了,详见代码。

AC代码如下:

 #include<stdio.h>
#include<string.h>
#define N 100010
int d[N],n;
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int num)
{
while(x>)
{
d[x]+=num;
x-=lowbit(x);
}
}
int sum(int x)
{
int s=;
while(x<=n)
{
s+=d[x];
x+=lowbit(x);
}
return s;
}
int main()
{
int i,a,b;
while(scanf("%d",&n)&&n)
{
memset(d,,sizeof(d));
for(i=;i<n;i++)
{
scanf("%d%d",&a,&b);
update(a-,-);
update(b,);
}
for(i=;i<n;i++)
printf("%d ",sum(i));
printf("%d\n",sum(n));
}
return ;
}