转载请注明出处:http://blog.csdn.net/u012860063
HDU 1166:http://acm.hdu.edu.cn/showproblem.php?pid=1166
题目分析
将一组数组a[N]
输入Query a b,输出SUM(ai + …… + aj)
输入Add i j,s[i] = s[i] + j
输入Sub i j,s[j] = s[i] - j
数组动态求和,明显的树状数组,调用树状数组模版:树状数组
一,每次修改的是一个点,所求的是关于某段区间;
直接贴模板:
#include
#include
#define maxn 50047
int c[maxn], a[maxn];
int n,t;
int Lowbit(int x) // 2^k
{
return x&(-x);
}
void update(int i, int x)//i点增量为x
{
while(i <= n)
{
c[i] += x;
i += Lowbit(i);
}
}
int sum(int x)//区间求和 [1,x]
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=Lowbit(x);
}
return sum;
}
int Getsum(int x1,int x2) //求任意区间和
{
return sum(x2) - sum(x1-1);
}
int main()
{
int i , j;
scanf("%d",&t);
int count = 0;
while(t--)
{
count++;
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
scanf("%d",&n);
for(i = 1; i <= n; i++) //i须从1开始
{
scanf("%d",&a[i]);
update(i,a[i]); //初始的人数
}
printf("Case %d:\n",count);
char oper[11];
while(scanf("%s",oper)==1)
{
if(strcmp(oper,"End")==0)
break;
scanf("%d%d",&i,&j);
if(strcmp(oper,"Query")==0)
{
printf("%d\n",Getsum(i,j));
}
if(strcmp(oper,"Add")==0) //表示第i个营地增加j个人
{
a[i] += j;
update(i,j);
}
if(strcmp(oper,"Sub")==0) //表示第i个营地减少j个人
{
a[i] -= j;
update(i,-j);
}
}
}
return 0;
}
-------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------
二,每次修改的是一个区间,所求的值是关于某个点的;
-------------------------------------------------------
模板如下:(HDU1556:http://acm.hdu.edu.cn/showproblem.php?pid=1556)
其实就是修改了update和sum函数里面的符号。
int Lowbit(int x) // 2^k
{
return x&(-x);
}
void update(int i,int x)
{
while(i>0)
{
c[i]+=x;
i-=Lowbit(i);
}
}
int sum(int x)
{
int sum=0;
while(x<=n)
{
sum+=c[x];
x+=Lowbit(x);
}
return sum;
}