原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166
分析:
今天看了树状数组,发现树状数组解这道题,方便很多呀↖(^ω^)↗,
刘汝佳的《算法竞赛入门经典——训练指南》的194页,树状数组就讲的很好。 实在是不懂就记住普通数组转换成树状数组的公式得了,还是要清楚树状数组的存储结构。
C[i]为树状数组,A[i]为普通数组。
我的代码:
#include<stdio.h>
#include<stdlib.h>
#define MANX 50000+10
int A[MANX];
int C[MANX];
int n;
int lowbit(int x)
{
return x&(-x);
}
int C_sum(int x) //求数组下标中[1,x]的和。
{
int sum=0;
while(x>0)
{
sum+=C[x];
x-=lowbit(x);
}
return sum;
}
void C_Modify(int index,int M) //在数组下标为index 的位置更新值。
{
while(index<=n) //n为元素个数。
{
C[index]+=M;
index+=lowbit(index);
}
}
int main()
{
int t;
int i,j,cas;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",A+i);
C[i]=0; //每次要初始化树状数组,之前没初始就WA了 o(︶︿︶)o.
}
for(i=1;i<=n;i++) //创建树状数组。
{
j=i-lowbit(i)+1;
for(;j<=i;j++)
{
C[i]+=A[j];
}
}
char str[10];
printf("Case %d:\n",cas);
while(~scanf("%s",str)&&str[0]!='E')
{
int a,b;
scanf("%d%d",&a,&b);
switch(str[0])
{
case 'A':C_Modify(a,b);break;
case 'S':C_Modify(a,-b);break;
case 'Q':
{
int sum1,sum2;
sum2=C_sum(b);
if(a-1==0) sum1=0;
else sum1=C_sum(a-1);
printf("%d\n",sum2-sum1);
break;
}
}
}
}
return 0;
}
总结:其实树状数组就是一个两个公式呀。更白一点就是由普通数组转换成树状数组的公式。