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 ...
随机推荐
- matlab rand(3,5)
rand()函数在(0,1)上创建均匀分布的随机数的数组 >> rand(3,5) ans = 0.8147 0.9134 0.2785 0.9649 0.9572 0.9058 0.63 ...
- pecl的使用
1. 安装方法 : pecl install packagename, 安装目录在/usr/local/php7/lib/php/extensions 例如:pecl install sealog 2 ...
- ROS Learning-031 (提高篇-009 A Mobile Base-07) 控制移动平台 --- (操作)人机交互
ROS 提高篇 之 A Mobile Base-07 - 控制移动平台 - (操作)人机交互 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 14 ...
- Java-马士兵设计模式学习笔记-策略模式-模拟 Comparator接口
续上一篇 <Java 模拟 Comparable接口> 一.Teacher类及Student类的比较大小方式是不固定的,比如老师除了比较职称外,还可比较工龄大小,年龄大小等.则定义Com ...
- LeetCode第111题:二叉树的最小深度
问题描述 给定一个二叉树,找出其最小深度. 最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明: 叶子节点是指没有子节点的节点. 示例: 给定二叉树 [3,9,20,null,null,1 ...
- 《Head First Servlets & JSP》-2-概述
什么是容器 Servlet没有main()方法,他们受控于另一个Java应用,这个java应用称为容器(Container). Web服务器应用(如Apache)得到一个指向Servlet的请求(如何 ...
- Spring MVC 简介
- Cookies的两种存取方式
我们在使用webview开发时,少不了和cookie打交道,在网页端我这使用的是asp.net开发的,安卓下的cookie和windows平台下还是有些不同的,后来看了看,原来有两种cookie的存取 ...
- mysql字段名与关键字冲突(near "to":syntax error)
今天遇到个问题,mysql字段为 to ,但是插入时报语法错误,仔细分析to是关键词 使用单引号和双引号 全部失败!!!! 仔细看 mysql的字段都是`(键盘Esc下面那个符号)括起来的, 试了一下 ...
- python web开发之flask框架学习(2) 加载模版
上次学习了flask的helloword项目的创建,这次来学习flask项目的模版加载: 第一步:创建一个flask项目 第二步:在项目目录的templates文件夹下创建一个html文件 第三步: ...