hdu 1166 敌兵布阵(数据结构:树状数组||线段树)
2014-07-19 16:44
330 查看
简单入门的树状数组题目
对应典型的树状数组操作
对照白书的写法:
可以在输入的过程中构造c数组,而不是等a数组输入完成后再构造c数组
代码如下:
学习线段树之后觉得线段树较树状数组易于理解
下面是线段树的代码:
对应典型的树状数组操作
对照白书的写法:
#include <stdio.h> #include <string.h> #define MAXN 50010 int a[MAXN+100], c[MAXN+100]; int lowbit(int x) { return x&(-x); } int sum(int x) { int sum = 0; while(x > 0) { sum += c[x]; x -= lowbit(x); } return sum; } void add(int x, int d) { while(x <= MAXN) { c[x] += d; x += lowbit(x); } } int main(void) { int T, t, i, j, N; char str[100]; scanf("%d", &T); for(t=1; t<=T; ++t) { scanf("%d", &N); memset(c, 0, sizeof(c)); for(i=1; i<=N; ++i) { scanf("%d", &a[i]); for(j=i-lowbit(i)+1; j<=i; ++j) c[i] += a[j]; } printf("Case %d:\n", t); while(scanf("%s", str) && strcmp(str, "End")) { scanf("%d%d", &i, &j); switch(str[0]) { case 'A': add(i, j); break; case 'S': add(i, -j); break; case 'Q': printf("%d\n", sum(j)-sum(i-1)); break; } } } }看了别人的代码,a数组并不是必要的
可以在输入的过程中构造c数组,而不是等a数组输入完成后再构造c数组
代码如下:
#include <stdio.h> #include <string.h> #define MAXN 50010 int a, c[MAXN+100]; int lowbit(int x) { return x&(-x); } int sum(int x) { int sum = 0; while(x > 0) { sum += c[x]; x -= lowbit(x); } return sum; } void add(int x, int d) { while(x <= MAXN) { c[x] += d; x += lowbit(x); } } int main(void) { int T, t, i, j, N; char str[100]; scanf("%d", &T); for(t=1; t<=T; ++t) { scanf("%d", &N); memset(c, 0, sizeof(c)); for(i=1; i<=N; ++i) { scanf("%d", &a); add(i, a);//等价于上面代码中c的构造公式 } printf("Case %d:\n", t); while(scanf("%s", str) && strcmp(str, "End")) { scanf("%d%d", &i, &j); switch(str[0]) { case 'A': add(i, j); break; case 'S': add(i, -j); break; case 'Q': printf("%d\n", sum(j)-sum(i-1)); break; } } } }
学习线段树之后觉得线段树较树状数组易于理解
下面是线段树的代码:
#include <cstdio> #include <iostream> #include <algorithm> #define MAXN 50010 #define LL long long using namespace std; 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(l, m, rt<<1); build(m+1, r, rt<<1|1); pushUp(rt); } void update(int p, int add, int l, int r, int rt) {//单点更新,令p点对应值+add, l r表示左右边界, rt表示根节点 if(l == r) { sum[rt] += add; return ; } int m = (l+r) >> 1; if(p <= m) update(p, add, l, m, rt<<1); else update(p, add, m+1, r, rt<<1|1); pushUp(rt); } int query(int L, int R, int l, int r, int rt) {//统计L R之间的叶节点之和,l r表示左右边界, rt表示根节点 if(L<=l && r<=R) return sum[rt]; int m = (l+r) >> 1; int ret = 0; if(L <= m) ret += query(L, R, l, m, rt<<1); if(R > m) ret += query(L, R, m+1, r, rt<<1|1); return ret; } int main(void) { int T, n; scanf("%d", &T); for(int t=1; t<=T; ++t) { printf("Case %d:\n", t); 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; }
相关文章推荐
- HDU 1166 敌兵布阵 (树状数组 || 线段树)
- hdu 1166 敌兵布阵 单点更新 树状数组 线段树 两种做法
- Hdu 1166 敌兵布阵 树状数组 或 线段树 单点更新,区间求和
- HDU 1166 敌兵布阵 (线段树基础&树状数组基础)
- HDU 1166 敌兵布阵 (树状数组和线段树解法)
- HDU-1166 敌兵布阵(树状数组和线段树)
- HDU 1166 敌兵布阵 (初学线段树 || 初学树状数组)
- hdu 1166 敌兵布阵【入门线段树 & 树状数组】
- hdu 1166 敌兵布阵(树状数组 or 线段树)
- HDU 1166 敌兵布阵(树状数组||线段树单点更新)
- HDU 1166 敌兵布阵(树状数组、sum型线段树)
- HDU1166 敌兵布阵 树状数组|线段树-构造完全二叉树(理解)
- 【HDU】-1166-敌兵布阵(树状数组,线段树)
- HDU 1166 敌兵布阵 树状数组||线段树
- HDU 1166 敌兵布阵(树状数组 or 线段树 单点修改 区间求和)
- HDU 1166 —— 敌兵布阵 【树状数组 or 线段树】
- HDU 1166 敌兵布阵【树状数组】【线段树】
- HDU 1166 敌兵布阵 我的第一棵树,线段树,树状数组。
- HDU - 1166 - 敌兵布阵(树状数组、线段树)
- hdu 1166 敌兵布阵(树状数组 | 线段树)