HDOJ-1166(线段树点更新 + 区间查询)
来源:互联网 发布:阿里云域名 编辑:程序博客网 时间:2024/06/07 00:54
试了一个完全二叉树,貌似效率有点低:
#include <cstdio>#include <cstring>struct SegmentTreeNode{ int l, r, n;} node[1 << (16 + 1) + 1];//2 ^ 16 = 65536 > 50000void build(int l, int r, int index){ node[index].l = l; node[index].r = r; node[index].n = 0; if(l == r) return; build(l, (r + l) >> 1, index << 1); build(((r + l) >> 1) + 1, r, (index << 1) + 1);}void addLeaf(int index, int n){ for(; index; index >>= 1) node[index].n += n;}int query(int l, int r, int index){ if(node[index].l == l && node[index].r == r) return node[index].n; int m = (node[index].l + node[index].r) >> 1; if(m >= r) return query(l, r, index << 1); else if(m < l) return query(l, r,(index << 1) + 1); else return query(l, m, index << 1) + query(m + 1, r, (index << 1) + 1);}int minInPower2(int num){ int n = 1; for(; n < num; n <<= 1) ; return n;}int main(){ int t, test, n, m, i, v; char cmd[8]; for(scanf("%d", &test), t = 1; t <= test; ++t){ printf("Case %d:\n", t); //input point count and get the minimum number in power 2 larger than count scanf("%d", &n); m = minInPower2(n); //build full binary segment tree build(1, m, 1); //init all leaves for(i = 0; i < n; ++i){ scanf("%d", &v); addLeaf(m + i, v); } //input operations while(true){ scanf(" %s", cmd); if(strcmp(cmd, "End") == 0) break; scanf("%d %d", &i, &v); if(strcmp(cmd, "Add") == 0) addLeaf(m + i - 1, v); else if(strcmp(cmd, "Sub") == 0) addLeaf(m + i - 1, -v); else printf("%d\n", query(i, v, 1)); } } return 0;}
再试了一下非完全二叉树:
#include <cstdio>#include <cstring>#define MAX_RANGE 50000struct SegmentTreeNode{ int l, r, n;} node[MAX_RANGE * 3];void build(int l, int r, int index){ node[index].l = l; node[index].r = r; node[index].n = 0; if(l == r) return; build(l, (r + l) >> 1, index << 1); build(((r + l) >> 1) + 1, r, (index << 1) + 1);}void addLeaf(int leaf, int num, int index){ node[index].n += num; if(node[index].l == node[index].r) return; int m = (node[index].l + node[index].r) >> 1; if(m >= leaf) addLeaf(leaf, num, index << 1); else addLeaf(leaf, num, (index << 1) + 1);}int query(int l, int r, int index){ if(node[index].l == l && node[index].r == r) return node[index].n; int m = (node[index].l + node[index].r) >> 1; if(m >= r) return query(l, r, index << 1); else if(m < l) return query(l, r,(index << 1) + 1); else return query(l, m, index << 1) + query(m + 1, r, (index << 1) + 1);}int main(){ int t, test, n, i, v; char cmd[8]; for(scanf("%d", &test), t = 1; t <= test; ++t){ printf("Case %d:\n", t); //input range and build tree scanf("%d", &n); build(1, n, 1); //init all leaves for(i = 1; i <= n; ++i){ scanf("%d", &v); addLeaf(i, v, 1); } //input operations while(true){ scanf(" %s", cmd); if(strcmp(cmd, "End") == 0) break; scanf("%d %d", &i, &v); if(strcmp(cmd, "Add") == 0) addLeaf(i, v, 1); else if(strcmp(cmd, "Sub") == 0) addLeaf(i, -v, 1); else printf("%d\n", query(i, v, 1)); } } return 0;}
貌似更慢了,目测是因为完全二叉树从下至上递推的更新区间比非完全二叉树从上至下递归的更新区间效率高些。
刚学了下树状数组,貌似树状数组的操作好简单的样子,而这一题简直就是为了树状数组而生的嘛:
#include <cstdio>#include <cstring>int n, C[50001] = {0};inline int lowbit(int x){ return x & -x; }void add(int x, int d){ while(x <= n){ C[x] += d; x += lowbit(x); }}int sum(int x){ int res = 0; while(x){ res += C[x]; x -= lowbit(x); } return res;}int main(){ int t, test, i, x, d; char cmd[8]; for(scanf("%d", &test), t = 1; t <= test; ++t){ printf("Case %d:\n", t); scanf("%d", &n); //initialize memset(C + 1, 0, n << 2); for(i = 1; i <= n; ++i){ scanf("%d", &d); add(i, d); } //operations while(scanf(" %s", cmd), strcmp(cmd, "End")){ scanf("%d %d", &x, &d); if(!strcmp(cmd, "Add")) add(x, d); else if(!strcmp(cmd, "Sub")) add(x, -d); else printf("%d\n", sum(d) - sum(x-1)); } } return 0;}可以看到无论在时间、空间、还是代码量上,树状数组都完胜啊,果真是个好东西……
0 0
- HDOJ-1166(线段树点更新 + 区间查询)
- HDOJ-1556(线段树||树状数组,区间更新+点查询)
- HDOJ-3974(线段树,区间修改点查询)
- HDOJ-1823(矩形树,点更新 + 区间查询)
- hdu1754 IHateIt (线段树点更新,区间查询)
- 线段树 (更新点查询区间)敌兵布阵
- 线段树 (更新区间查询点)Color the ball
- HDOJ 1166 点更新段查询求和 初级线段树
- HDU 1166 敌兵布阵 (线段树点更新区间查询)
- hdoj 4339 线段树 单点更新,区间查询
- hdoj 5493 Queue 【线段树 单点更新 + 区间查询】
- hdoj 4819 Mosaic 【二维线段树 单点更新 区间查询】
- HDOJ 5316 Magician【线段树 单点更新 区间查询】
- HDU1166线段树的点更新区间查询
- HDU1166:敌兵布阵(线段树点更新,区间查询)
- HDOJ 题目3954 Level up(线段树去见面更新区间查询)
- HDOJ 5596 GTW likes gt (线段树区间更新+单点查询+技巧)
- POJ 3237Tree(树链剖分-线段树点更新-区间更新-区间最值查询-入边)
- android-awesome-resource
- UIScrollView paging
- wxwidgets中分解GIF动画图片并显示播放
- leedcode做题总结,题目Reverse Integer----- 2011/12/25
- objective-c基础教程——学习小结
- HDOJ-1166(线段树点更新 + 区间查询)
- Android的MediaPlayer架构介绍
- IOS研究之IOS下TTS语音合成的几种方案
- <MFC笔记>BMP位图文件的格式及其操作
- eclipse快捷键
- android media
- 详解python linecache模块读取文件的方法
- Android中的so注入(inject)和挂钩(hook)
- Android的MediaPlayer架构介绍