HDU 1166 敌兵布阵(单点修改 区间查询)
原题
这是一道基于树状数组基本操作的板子题。
本题涉及到树状数组几个基本操作:
① 单点查询
int query(int x)
{
int ans=0;
for(;x;x-=(x&-x))
{
ans+=c[x];
}
return ans;
}
② 单点修改
void add(int i,int j)
{
for(;i<=n;i+=(i&-i))
{
c[i]+=j;
}
}
③ 区间查询
我们知道树状数组储存的是前缀和,所以要查询区间[l,r]中所有数的和,只需计算ask(r)-ask(l-1)。
所以该题只需简单的模拟即可,WA了一发的原因是因为忘记了树状数组要先初始化为0;
AC代码:
#include<bits/stdc++.h>
using namespace std;
int a[50005],c[50005],n;
int query(int x)//单点查询
{
int ans=0;
for(;x;x-=(x&-x))
{
ans+=c[x];
}
return ans;
}
void add(int i,int j)//单点修改
{
for(;i<=n;i+=(i&-i))
{
c[i]+=j;
}
}
int main()
{
int T,cnt=1;
cin>>T;
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]);
}
char b[10];
int i,j;
printf("Case %d:\n",cnt++);
while(~scanf("%s",b))
{
if(b[0]=='E')
break;
scanf("%d%d",&i,&j);
if(b[0]=='Q')
{
int x=query(i-1),y=query(j);
printf("%d\n",y-x);
}
else if(b[0]=='A')
{
add(i,j);
}
else if(b[0]=='S')
add(i,-j);
}
memset(c,0,sizeof(c));//要注意树状数组的初始化
}
return 0;
}
戒骄戒躁,百炼成钢!