线段树练习1
来源:互联网 发布:民国算法 编辑:程序博客网 时间:2024/06/15 23:30
虽然早就听说过线段树,而且内部讲课也讲了很多次,但今天才下定决心学习(有点懒哈~)
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶节点。 对于线段树中的每一个非叶子节点(编者注:即单点区间,也可以说最后一层)左儿子表示[l,mid],右儿子表示[mid + 1,r]。因此线段树是平衡二叉树,最后的子节点数目为n,即整个区间的长度。————来自百度百科
题目:> http://codevs.cn/problem/1080/
线段数的修改与查找时间复杂度都是O(logn),空间复杂度为4n - 1,但其中有很多空间是浪费的,用指针的话动态构建线段树就不会浪费空间,空间复杂度为2n -1,本着优化空间的原则,我就直接学的指针线段树。
首先是初始化:
注:指针存的是地址,&表示取地址。
struct zt{ int l,r,sum; zt *lift,*right;};void build(zt *root,int l,int r){ root->sum = 0;root->l = l;root->r = r; if(l == r) return; int mid = (l + r)>>1; root->lift = &tree[++cnt]; build(root->lift,l,mid); root->right = &tree[++cnt]; build(root->right,mid + 1,r);}
由于不同的题有不同的写法,关于这道题(单点更新,区间求和)代码如下:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN = 2e5 + 5;int n,m,a,b,cnt = 0;struct zt{ int l,r,sum; zt *lift,*right;};zt tree[MAXN];void build(zt *root,int l,int r){ root->sum = 0;root->l = l;root->r = r; if(l == r) return; int mid = (l + r)>>1; root->lift = &tree[++cnt]; build(root->lift,l,mid); root->right = &tree[++cnt]; build(root->right,mid + 1,r);}void add(zt *root,int i,int v){ if(root->l == i&&root->r == i) { root->sum+=v; return; } root->sum += v; int mid = (root->l + root->r)>>1; if(i > mid) add(root->right,i,v); else add(root->lift,i,v);}int query(zt *root,int l,int r,int ql,int qr){ if(ql <= l&&r <= qr) return root->sum; int mid = (l + r)>>1; if(ql > mid) return query(root->right,mid + 1,r,ql,qr); if(qr <= mid) return query(root->lift,l,mid,ql,qr); return (query(root->right,mid + 1,r,ql,qr) + query(root->lift,l,mid,ql,qr));}int main(){ scanf("%d",&n); build(tree,1,n); for(int i = 1;i <= n;i ++) { scanf("%d",&a); add(tree,i,a); } scanf("%d",&m); for(int i = 1;i <= m;i ++) { scanf("%d",&a); if(a == 1) { scanf("%d %d",&a,&b); add(tree,a,b); } else { scanf("%d %d",&a,&b); printf("%d\n",query(tree,1,n,a,b)); } } return 0;}
阅读全文
0 0
- 线段树1练习
- 线段树练习1
- 线段树练习1
- 线段树练习(1)
- 【codevs1080】线段树练习1
- [线段树练习1] 线段统计 - 线段树懒标记
- <线段树系列1> codevs 1080 线段树练习
- [codevs]: 线段树练习1-4
- 线段树练习
- Wikioi1080线段树练习
- 线段树练习
- 【wikioi1080】 线段树练习
- 线段树练习
- 线段树练习
- 线段树练习 2
- 线段树2练习
- 线段树练习3
- Codevs1080 线段树练习
- POJ 3070 Fibonacci
- JAVA集合类--几种特殊的Queue
- 【Java编程】String相关方法的使用(一)
- ios不触发事件也能播放音频
- 【PAT】【Advanced Level】1042. Shuffling Machine (20)
- 线段树练习1
- 一串奇怪的数:
- 持续集成之Jenkins(一)Jenkins安装
- How Many Tables HDU
- Spring 事物手动回滚
- 表单验证 datetype 使用
- Python——列表生成式备忘
- Codeforces785D (组合数的逆元)
- poj1496—Word Index(组合数)