周中记录--2017.9.7(线段树整理)
来源:互联网 发布:人工智能领域 编辑:程序博客网 时间:2024/06/05 03:08
开学第二周了。也终于逐渐稳定下来可以有条有序的处理问题了。首先说一点到现在为止的一点不足的地方,就是还没有去实验室学过习。这周末就要去做比赛了,周围都是大佬压力好大。。。
这周一直在忙的还有JAVA的学习,JAVA老师布置了很多很多的作业,虽然都是水题,但还是要认真完成。很多知识点感觉用到的需要上网去查,去学习。老师最新布置的题里,感觉。有些需要用搜索递归等去解决。写起来虽然和c++一样,但是vector,set等用法还是要去学习,这些和c++还是有区别的。虽然那些题可以暴力解决,没有给定数值范围,也没有时间限制,但是感觉如果用循环分分钟TLE。用算法解决还是要花一些时间的。但是也巩固了自己的知识点,也算是锻炼了自己。
再接下来的,就是研究了线段树的有关知识。下面写一下对线段树的理解总结。
线段树,有根节点和子节点还有父节点。它的本质就是一颗二叉树。线段树的每一个节点用于记录某一段区间上的信息。那么记录的是什么样的信息呢?线段树,首先是用来解决单点更新,区间查询,区间更新。那么线段树的每一个节点,储存的就是一段区间上的信息。对于任意一个非叶子节点,若该区间为[L,R],则左儿子节点为[L,(L+R)/2],右儿子节点为[(L + R)/2,R]。
线段树的实现:
#include <iostream>using namespace std;struct Tree{ int L,R; int max,sum;};用一个一维数组记录节点,且根节点的下标为1.那么对于任一节点a[k],其左儿子为a[2 * k],右儿子为a[2 * k + 1];
建立树也用到了类似递归的方式。源代码:
#include <iostream>using namespace std;struct Tree{ int L,R; int max,sum;}tree[1000];int a[1000];void build(int id,int l,int r){ tree[id].L = l; tree[id].R = r; if (l == r) { tree[id].sum = a[l]; tree[id].max = a[l]; } else { int mid = (l+r)/2; build(id*2 , l , mid); build(id*2+1 , mid+1 , r); tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum; tree[id].max = max(tree[id * 2].max, tree[id * 2 + 1].max); }}int main(){ int n; while (cin >> n){ for (int i = 1; i <= n; i++){ cin >> a[i]; } build(1,1,n); cout << tree[1].max << endl << tree[1].sum; }}/*6 // n1,5,4,1,6; // a[i]6 // cout(max)17 // cout(sum)*/下面是对于线段树的一些操作。
线段树和树状数组有些类似。但比树状数组好用。首先是单点更新。
即修改某一点的数值。
源代码:
void change(int id,int pos,int val)//pos即为要修改的位置{ if (tree[id].L == tree[id].R) tree[id].sum = tree[id].max = val;//val即更新的值 else { int mid = (tree[id].L + tree[id].R)/2; if (pos <= mid) change(id * 2,pos,val); else change(id * 2 + 1,pos,val); tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum; tree[id].max = max(tree[id * 2].max,tree[id * 2 + 1].max); }}
接下来是另一项基本操作。和树状数组类似,就是查询某一段区间元素和和最大值。因为之前树种保存了,所以查询还是比较好实现的。
下面附查询总和的源代码:
int getsum(int id,int l,int r){ if (tree[id].L == l && tree[id].R == r) return tree[id].sum; else { int mid = (tree[id].L + tree[id].R)/2; if (r <= mid) return getsum(id * 2,l,r); else if (l > mid) return getsum(id * 2 + 1,l,r); else return getsum(id * 2,l,mid) + getsum(id * 2 + 1,mid + 1,r); }}下面附查询最大值的源代码:
int getmax(int id,int l,int r){ if (tree[id].L == l && tree[id].R == r) return tree[id].max; else { int mid = (tree[id].L + tree[id].R) / 2; if (r <= mid) return getmax(id * 2,l,r); else if (l > mid) return getmax(id * 2 + 1,l,r); else return max(getmax(id * 2,l,mid),getmax(id * 2 + 1,mid + 1,r)); }}
主函数:
int main(){ int n; while (cin >> n){ for (int i = 1; i <= n; i++){ cin >> a[i]; } build(1,1,n); cout << tree[1].max << endl << tree[1].sum << endl; cout << "l:" ; int l,r; cin >> l; cout << endl << "r:"; cin >> r; cout << endl; cout <<"sum:" << getsum(1,l,r); cout << "max:" << getmax(1,l,r); }}
操作的事主要就是从头开始往下寻找。然后对这个线段树进行操作。可能还有别的操作,但是还没有学习还没有进行总结。以后再进行总结吧。
hdoj上有道题,看看把它做了吧。然后再去水几道JAVA作业题。
周末的练习赛,按时参加,赛后补题,记得记得!!
- 周中记录--2017.9.7(线段树整理)
- 线段树整理
- 线段树整理
- 线段树题型整理
- 线段树整理
- 线段树代码整理
- 线段树模板整理
- 线段树整理
- 线段树整理
- 线段树学习记录
- 线段树 学习记录
- 线段树+树状数组整理
- stm32f407 学习过程中时钟问题(整理记录)
- 线段树(更新中)
- 线段树的学习记录
- 记录一下zkw线段树
- hdu 1540 Tunnel Warfare (线段树 记录的信息)
- Oracle中删除重复记录整理
- Java中的关系操作符
- C# 创建验证码图片
- ACM周中总结—9月7日
- bzoj2763 [JLOI2011]飞行路线(分层图最短路)
- jsp之间url传值,接值
- 周中记录--2017.9.7(线段树整理)
- es6 map和 weakmap
- JSP动作元素
- HDU 3068 最长回文(Manacher)
- PID调节经验
- 已有java文件添加到工程中的两种方法
- Ubuntu16.04 安装Python开发环境
- Leetcode学习日志-376 Wiggle Subsequence
- HDU 5996 Nim博弈