敌兵布阵Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 116768 Accepted Submission(s): 48926 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。
Input 第一行一个整数T,表示有T组数据。
Output 对第i组数据,首先输出“Case i:”和回车,
Sample Input 1 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End
Sample Output Case 1: 6 33 59
|
同样的问题我们可以有不同的解法,这次我们就要学习一下树状数组
lowbit,这样一个函数完成了树状数组的绝大部分计算任务,应为通过 +lowbit(x),-lowbit(x)我们可以找到 x 点的下一个父节点和上一个父节点,通过lowbit我们可以完成对要修改的值的传递,同样的,我们在进行区间查询是,可以通过查 终点的值 减去 起点 - 1的值 来完成区间查询。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int MAXN = 50005;
int c[MAXN];
int num[MAXN];
int n;
int lowbit(int x)
{
return x & -x;
}
void update(int x, int y)
{
for(int i = x; i <= n; i += lowbit(i))
c[i] += y;
}
int query(int x)
{
int ans = 0;
for(int i = x; i > 0; i -= lowbit(i))
ans += c[i];
return ans;
}
int main()
{
int T;
scanf("%d", &T);
for(int cas = 1; cas <= T; cas++)
{
scanf("%d", &n);
memset(c, 0, sizeof(c));
memset(num, 0, sizeof(num));
for(int i = 1; i <= n; i++)
{
scanf("%d", &num[i]);
update(i, num[i]);
}
printf("Case %d:\n", cas);
int a, b;
char op[10];
while(~scanf("%s", op))
{
if(op[0] == 'Q')
{
int a, b;
scanf("%d %d", &a, &b);
printf("%d\n", query(b) - query(a - 1));
}
else if(op[0] == 'A')
{
int a, b;
scanf("%d %d", &a, &b);
update(a, b);
}
else if(op[0] == 'S')
{
int a, b;
scanf("%d %d", &a, &b);
update(a, -b);
}
else
break;
}
}
return 0;
}