java——线段树 SegmentTree
应用:
区间染色
区间查询
线段树不是完全二叉树,线段树是平衡二叉树
使用数组来实现线段树:存储空间为4n
以下是使用数组实现的静态线段树:
public class SegmentTree<E> { private E[] tree;
private E[] data;
private Merger<E> merger; public SegmentTree(E[] arr, Merger<E> merger) {
this.merger = merger;
data = (E[]) new Object[arr.length];
for(int i = 0 ; i < arr.length ; i ++) {
data[i] = arr[i];
} tree = (E[]) new Object[4 * arr.length];
buildSegmentTree(0, 0, data.length - 1);
}
//在tree Index的位置创建表示区间[l ... r]的线段树
private void buildSegmentTree(int treeIndex, int l, int r) { if(l == r) {
tree[treeIndex] = data[l];
return;
} int leftTreeIndex = leftChild(treeIndex);
int rightTreeIndex = rightChild(treeIndex);
int mid = l + (r - l) / 2;
buildSegmentTree(leftTreeIndex, l, mid);
buildSegmentTree(rightTreeIndex, mid + 1, r); //根据业务组合线段树
tree[treeIndex] = merger.merge(tree[leftTreeIndex], tree[rightTreeIndex]);
} public E get(int index) {
if(index < 0 || index >= data.length) {
throw new IllegalArgumentException("Index is illegal.");
}
return data[index];
} public int getSize() {
return data.length;
} private int leftChild(int index) {
return 2*index + 1;
} private int rightChild(int index) {
return 2*index + 2;
} public E query(int queryL, int queryR) {
if(queryL < 0 || queryL >= data.length || queryR < queryL){
throw new IllegalArgumentException("Index is illegal.");
}
return query(0, 0, data.length -1, queryL, queryR);
}
//查询线段树
//在以treeID为根的线段树中[l...r]的范围里,搜索区间[queryL...queryR]的值
private E query(int treeIndex, int l, int r, int queryL, int queryR) {
if(l == queryL && r == queryR) {
return tree[treeIndex];
} int mid = l + (r-l)/2;
int leftTreeIndex = leftChild(treeIndex);
int rightTreeIndex = rightChild(treeIndex); if(queryL >= mid +1) {
return query(rightTreeIndex, mid + 1, r, queryL, queryR);
}else if(queryR <= mid) {
return query(leftTreeIndex, l, mid, queryL, queryR);
}else {
//这种情况下产生了两段线段树,需要进行融合
E leftResult = query(leftTreeIndex, l, mid, queryL, mid);
E rightResult = query(rightTreeIndex, mid + 1, r, mid + 1, queryR);
return merger.merge(leftResult, rightResult);
}
}
//将index位置的值更新为e
public void set(int index, E e) {
if(index < 0 || index >= data.length) {
throw new IllegalArgumentException("Index is illegal");
}
data[index] = e;
set(0,0, data.length - 1, index, e);
} private void set(int treeIndex, int l, int r, int index, E e) {
if(l == r) {
tree[treeIndex] = e;
return;
} int mid = l + (r - l) / 2;
int leftTreeIndex = leftChild(treeIndex);
int rightTreeIndex = rightChild(treeIndex);
if(index >= mid + 1) {
set(rightTreeIndex, mid + 1, r, index, e);
}else {
set(leftTreeIndex, l, mid, index, e);
} tree[treeIndex] = merger.merge(tree[leftTreeIndex], tree[rightTreeIndex]);
} @Override
public String toString() {
StringBuilder res = new StringBuilder();
res.append('[');
for(int i = 0 ; i < tree.length ; i ++) {
if(tree[i] != null) {
res.append(tree[i]);
}else {
res.append("null");
}
if(i != tree.length - 1) {
res.append(", ");
}
}
res.append("]");
return res.toString();
} }
对于一个区间的更新:
懒惰更新:使用lazy数组记录未更新的内容,下一次访问时先访问lazy数组,若有内容,更新后再访问即可。
动态线段树:
使用链表实现
节省空间
可以不均等划分区间,便于实际应用
java——线段树 SegmentTree的更多相关文章
- [java线段树]2015上海邀请赛 D Doom
题意:n个数 m个询问 每个询问[l, r]的和, 再把[l, r]之间所有的数变为平方(模为9223372034707292160LL) 很明显的线段树 看到这个模(LLONG_MAX为922337 ...
- Java线段树
线段树不是完全二叉树,是平衡二叉树 堆也是平衡二叉树 堆满二叉树: h层,一共有2^h-1个节点(大约是2^h) 最后一层(h-1层)有2^(h-1)个节点 最后一层的节点数大致等于前面所有层节点之和 ...
- 模板 - 数据结构 - 线段树/SegmentTree
区间求加法和: 单点修改的,普通线段树. struct SegmentTree { #define ls (o<<1) #define rs (o<<1|1) static c ...
- 【LeetCode】线段树 segment-tree(共9题)+ 树状数组 binary-indexed-tree(共5题)
第一部分---线段树:https://leetcode.com/tag/segment-tree/ [218]The Skyline Problem [307]Range Sum Query - Mu ...
- 线段树(SegmentTree)基础模板
线段树模板题来源:https://www.lintcode.com/problem/segment-tree-build/description 201. 线段树的构造 /** * Definitio ...
- 【hihoCoder】第20周 线段树
题目: 输入 每个测试点(输入文件)有且仅有一组测试数据. 每组测试数据的第1行为一个整数N,意义如前文所述. 每组测试数据的第2行为N个整数,分别描述每种商品的重量,其中第i个整数表示标号为i的商品 ...
- java 操作格子问题(线段树)
很久之前做过线段树的问题(操作格子),时间长了之后再次接触到,发现当初理解的不是很透彻,然后代码冗长,再遇到的时候发现自己甚至不能独立地完成这个问题. 所以算法这个东西啊, 第一,是要经常练习(我个人 ...
- POJ——3264线段树
题目: 输入两个数(m,n),m表示牛的头数,n表示查询的个数.查询时输入两个数(x,y),表示查询范围的起始值和终止值,查询结果是,这个区间内牛重量的最大值减去牛重量的最小值,数量级为1000,00 ...
- lintcode:线段树的查询
线段树的查询 对于一个有n个数的整数数组,在对应的线段树中, 根节点所代表的区间为0-n-1, 每个节点有一个额外的属性max,值为该节点所代表的数组区间start到end内的最大值. 为Segmen ...
随机推荐
- IFC文档结构说明
工业基础类为代表的建筑信息BIM数据交换和共享在一个建筑或设施管理项目各参与者之间的开放规范的建模.IFC是国际openbim标准.本文件包含的IFC标准的规范.该规范包括的数据架构,表示为一个表达模 ...
- 【转】nginx禁止访问某个文件和目录(文件夹)
nginx禁止访问所有.开头的隐藏文件设置 location ~* /.* {deny all;} nginx禁止访问目录, 例如:禁止访问path目录 location ^~ /path {deny ...
- 面试题:AOP面向切面编程
//创建一个与代理对象相关联的InvocationHandler InvocationHandler stuHandler = new MyInvocationHandler<Person> ...
- scau 2015寒假训练
并不是很正规的.每个人自愿参与自愿退出,马哥找题(马哥超nice么么哒). 放假第一周与放假结束前一周 2015-01-26 http://acm.hust.edu.cn/vjudge/contest ...
- 移除HTML标签(CharacterUtility)类库
最近时间,专案需要,写了一个类库,主要是为了移除HTML标签以及截取前一段文本的类库. 下载地址:http://download.cnblogs.com/insus/Library/Character ...
- Data Base System.Data.OracleClient requires Oracle client software version 8.1.7 or greater解决方案
System.Data.OracleClient requires Oracle client software version 8.1.7 or greater解决方案 一.问题: 1.通过Syst ...
- javascript javascript加载类似星座、血型的函数
javascript加载类似星座.血型的函数 //加载血型 function bloodtypelaod(constellation) { var obj = document.getElement ...
- Java整体之JavaEE
思维导图 (Xmind)链接:http://pan.baidu.com/s/1pKTOTRH 密码:oq7f <iframe src="http://www.xmind.net/emb ...
- SQL sum和group by HAVING
Aggregate functions (like SUM) often need an added GROUP BY functionality. 集合函数(类似SUM)经常需要用GROUP BY来 ...
- UVA10173 Smallest Bounding Rectangle 最小面积矩形覆盖
\(\color{#0066ff}{题目描述}\) 给定n(>0)二维点的笛卡尔坐标,编写一个程序,计算其最小边界矩形的面积(包含所有给定点的最小矩形). 输入文件可以包含多个测试样例.每个测试 ...