|
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1166
/**//* 题意: 给定N(N <= 50000)个数, 表示敌人有N个工兵营地,接下来有N个正整数, 第 i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。 接下来每行有一条命令,命令有4种形式: (1)Add i j ,i和j为正整数, 表示第i个营地增加j个人(j不超过30) (2)Sub i j ,i和j为正整数, 表示第i个营地减少j个人(j不超过30); (3)Query i j ,i和j为正整数, i<=j,表示询问第i到第j个营地的总人数; (4)End 表示结束,这条命令在每组数据最后出现
解法: 树状数组 或者 线段树
思路: 典型的树状数组模板题,Add和Sub是同一个操作,Sub就是Add一个负的值,只 是Sub之前先要判断这个点有没有这么多,询问就是利用树状数组的成段求和。 */
#include <iostream>
using namespace std;
#define maxn 1000010
int c[maxn], n; int a[maxn]; char ch[100];
int lowbit(int x) { return x & (-x); }
void Add(int x, int add) { while(x <= n) { c[x] += add; x += lowbit(x); } }
int sum(int x) { int s = 0; while(x > 0) { s += c[x]; x -= lowbit(x); } return s; }
int main() { int t, as, bs, i, q = 1; scanf("%d", &t); while(t--) { scanf("%d", &n); memset(c, 0, sizeof(c)); for(i = 1; i <= n ;i++) { scanf("%d", &a[i]); Add(i, a[i]); } printf("Case %d:\n", q++); while(scanf("%s" , ch) != EOF) { if(!strcmp(ch, "End")) break; else if(!strcmp(ch, "Query")) { scanf("%d%d", &as, &bs); printf("%d\n", sum(bs) - sum(as - 1)); }else if(!strcmp(ch, "Add")) { scanf("%d%d", &as, &bs); Add(as, bs); } else if(!strcmp(ch, "Sub")) { scanf("%d%d", &as, &bs); Add(as, -bs); } } } }
|