应用:

  区间染色

  区间查询

线段树不是完全二叉树,线段树是平衡二叉树

使用数组来实现线段树:存储空间为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的更多相关文章

  1. [java线段树]2015上海邀请赛 D Doom

    题意:n个数 m个询问 每个询问[l, r]的和, 再把[l, r]之间所有的数变为平方(模为9223372034707292160LL) 很明显的线段树 看到这个模(LLONG_MAX为922337 ...

  2. Java线段树

    线段树不是完全二叉树,是平衡二叉树 堆也是平衡二叉树 堆满二叉树: h层,一共有2^h-1个节点(大约是2^h) 最后一层(h-1层)有2^(h-1)个节点 最后一层的节点数大致等于前面所有层节点之和 ...

  3. 模板 - 数据结构 - 线段树/SegmentTree

    区间求加法和: 单点修改的,普通线段树. struct SegmentTree { #define ls (o<<1) #define rs (o<<1|1) static c ...

  4. 【LeetCode】线段树 segment-tree(共9题)+ 树状数组 binary-indexed-tree(共5题)

    第一部分---线段树:https://leetcode.com/tag/segment-tree/ [218]The Skyline Problem [307]Range Sum Query - Mu ...

  5. 线段树(SegmentTree)基础模板

    线段树模板题来源:https://www.lintcode.com/problem/segment-tree-build/description 201. 线段树的构造 /** * Definitio ...

  6. 【hihoCoder】第20周 线段树

    题目: 输入 每个测试点(输入文件)有且仅有一组测试数据. 每组测试数据的第1行为一个整数N,意义如前文所述. 每组测试数据的第2行为N个整数,分别描述每种商品的重量,其中第i个整数表示标号为i的商品 ...

  7. java 操作格子问题(线段树)

    很久之前做过线段树的问题(操作格子),时间长了之后再次接触到,发现当初理解的不是很透彻,然后代码冗长,再遇到的时候发现自己甚至不能独立地完成这个问题. 所以算法这个东西啊, 第一,是要经常练习(我个人 ...

  8. POJ——3264线段树

    题目: 输入两个数(m,n),m表示牛的头数,n表示查询的个数.查询时输入两个数(x,y),表示查询范围的起始值和终止值,查询结果是,这个区间内牛重量的最大值减去牛重量的最小值,数量级为1000,00 ...

  9. lintcode:线段树的查询

    线段树的查询 对于一个有n个数的整数数组,在对应的线段树中, 根节点所代表的区间为0-n-1, 每个节点有一个额外的属性max,值为该节点所代表的数组区间start到end内的最大值. 为Segmen ...

随机推荐

  1. ROS Learning-024 (提高篇-002) rviz的安装和使用

    ROS 提高篇-002 - rviz 的安装和使用 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 14.04.4 LTS ROS 版本:ROS ...

  2. java中字符串的存储

    在java中,不同的字符串赋值方法,其所在的地址可能不同也就导致,两个字符串的值看似相等可是在s1==s2操作时,其结果返回的却是false 例: String s1 = "Programm ...

  3. Libcurl 简明使用指南

    http://blog.csdn.net/weiling_shen/article/details/7620397 我们的程序中使用的是人家的Easy.h头文件.....完成文件的上传和下传. 尤其是 ...

  4. linux deb及rpm格式软件安装

    deb格式软件安装 deb包是debian,ubuntu等LINUX发行版的软件安装包,是类似于rpm的软件包,而非debian,ubuntu系统不推荐使用deb软件包,因为要解决软件包依赖问题,安装 ...

  5. 删除GHOST中win7桌面IE删不掉的解决办法

    打开Win+R 运行regedit 依次打开: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Deskto ...

  6. 8.8 Deep Learning Software

    深度学习软件 -CPU vs GPU -Deep Learning Framework - Caffe / Caffe2 - Theano / TensorFlow - Torch / PyTorch ...

  7. linux文件链接

    我的github,欢迎关注,分享知识与技术 链接:一种在共享文件和访问它的用户的若干目录项之间建立联系的一种方法. Linux中包括两种链接:硬链接(HardLink)和软链接(Soft Link), ...

  8. java 文件的读写操作

    java  文件的读写操作 一.读: public String getSetting() { HttpServletRequest request=org.apache.struts2.Servle ...

  9. Spring Boot 学习系列(02)—使用热部署,提升开发效

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 开发调试很简单 热部署的使用非常简单,但能极大的提高我们的开发效率,像传统的web应用,我们修改后需要重新编 ...

  10. 「ZOJ 1354」Extended Lights Out「高斯消元」

    题意:给定一个\(5\times 6\)的棋盘的\(01\)状态,每次操作可以使它自己和周围四个格子状态取反,求如何操作,输出一个\(01\)矩阵 题解:这题可以通过枚举第一行的状态然后剩下递推来做, ...