标签:des style blog http color io os ar for
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166
Description
Input
Output
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
题意:一维线性的直线上,排列着n个兵营,初始每个兵营有固定的人数,有两个操作:一个是添加,把某个兵营增加人数d;二是询问,求某两个兵营之间所有兵营的总人数之和。
解题思路:这个题以前用树状数组写过,是很基础的树状数组模板题,也是很基础的线段树的题目,因为在内存允许的情况下,能用树状数组切的题,线段树都能切,线段树还有好多树状数组搞不定的功能,很神奇哦~~~只不过,线段树写着比树状数组复杂多了,树状数组最大的优点就是简单,所以能用树状数组切的题,就不要用线段树做!
但是,今天用线段树重切这题,是因为要搞线段树了,先从基本的搞起,是为了学习线段树才写的。。。
树状数组解法 HDU 1166 敌兵布阵 (树状数组)
关于线段树的基本内容,详见 线段树之入门篇
AC代码:
#include <cstdio>
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 55555;
int sum[maxn<<2];
void PushUP(int rt) {
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void build(int l,int r,int rt) { //建树
if (l == r) {
scanf("%d",&sum[rt]);
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUP(rt);
}
void update(int p,int add,int l,int r,int rt) { //更新
if (l == r) {
sum[rt] += add;
return ;
}
int m = (l + r) >> 1;
if (p <= m) update(p , add , lson);
else update(p , add , rson);
PushUP(rt);
}
int query(int L,int R,int l,int r,int rt) { //询问
if (L <= l && r <= R) {
return sum[rt];
}
int m = (l + r) >> 1;
int ret = 0;
if (L <= m) ret += query(L , R , lson);
if (R > m) ret += query(L , R , rson);
return ret;
}
int main() {
int T , n;
scanf("%d",&T);
for (int cas = 1 ; cas <= T ; cas ++) {
printf("Case %d:\n",cas);
scanf("%d",&n);
build(1 , n , 1);
char op[10];
while (scanf("%s",op)) {
if (op[0] == 'E') break;
int a , b;
scanf("%d%d",&a,&b);
if (op[0] == 'Q') printf("%d\n",query(a , b , 1 , n , 1));
else if (op[0] == 'S') update(a , -b , 1 , n , 1);
else update(a , b , 1 , n , 1);
}
}
return 0;
}
标签:des style blog http color io os ar for
原文地址:http://blog.csdn.net/u013446688/article/details/39813831