标签: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