题意分析:
查询区间敌兵数。
解题思路:
模板题啦,可以用各种方法过。这里当做树状数组入门。
推荐一篇博文来入门:http://blog.csdn.net/pi9nc/article/details/8779483#t1
博文的第二部分就是关于树状数组的。
个人感受:
整个树状数组我觉得最需要抓住的是sum数组是存储着什么这个核心。
明白了sum数组存储着什么,由这个定义进而衍生出的函数lowbit,单点更新,都能轻松理解了。
具体细节看看代码吧,加了点注释。
具体代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
const int MAXN = 5e4 + 111;
int a[MAXN], sum[MAXN], n; // sum[i]中存储的是其管辖的从i ~ i-2^k + 1的数的和(k是到第一个1为止0的个数)
int lowbit(int x) // 返回二进制从右往左第一个1代表的数。
{
return x & -x;
}
void init(int n) // 初始化(这样初始化可以避免对sum数组的初始化eg. memset(sum, 0, sizeof sum)这一步就可以省掉了)
{
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
sum[i] = a[i];
for (int j = 1; j < lowbit(i); j <<= 1) // 与所有涉及到的子区间段求和
{
sum[i] += sum[i - j];
}
}
}
int getSum(int x) // 整个原理就是将x按1的个数区分成段,将每段和相加
{
int res = 0;
while (x > 0)
{
res += sum[x];
x -= lowbit(x);
}
return res;
}
void add(int x, int val) // 和getSum同理,不断更新每个段的值
{
while (x <= n)
{
sum[x] += val;
x += lowbit(x);
}
}
int main()
{
int t, x, y; scanf("%d", &t);
for (int kase = 1; kase <= t; ++kase)
{
scanf("%d", &n);
init(n);
char op[8];
printf("Case %d:\n", kase);
while (scanf("%s", op))
{
if (op[0] == 'E') break;
scanf("%d%d", &x, &y);
if (op[0] == 'Q')
printf("%d\n", getSum(y) - getSum(x - 1));
else if (op[0] == 'A')
add(x, y);
else add(x, -y);
}
}
return 0;
}