应用:

  区间染色

  区间查询

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

使用数组来实现线段树:存储空间为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. libmad介绍

    一.简介 libmad是一个开源mp3解码库,其对mp3解码算法做了很多优化,性能较好,很多播放器如mplayer.xmms等都是使用这个开源库进行解码的:如果要设计mp3播放器而又不想研究mp3解码 ...

  2. matlab任务:FCM分类

    一个朋友让帮忙做图像分类,用FCM聚类算法,网上查了一下,FCM基本都是对一幅图像进行像素的分类,跟他说的任务不太一样,所要做的是将一个文件夹里的一千多幅图像进行分类.图像大概是这个样子的(是25*2 ...

  3. [译]内联Javascript vs 外置Javascript

    本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...

  4. 删除iCloud手机备份

    问题描述 系统9.3.5提示iCloud空间即将满,遂清理一下,发现空间主要被备份文件占用,于是想着删除备份文件,但是手机中的清理iCloud列表中并未找到相关备份文件.最终通过Mac电脑中的iClo ...

  5. ServletContext接口(六)

    javax.servlet.ServletContext接口 ServletContext(上下文)是公用的,就是.net中的application,主要用到的就是全局set设置值,get获取值,ja ...

  6. 关于windows2012-远程复制粘贴无效的解决方法

    1:在远程桌面中右键点击,选择启动任务管理器,杀掉进程 2:重启服务即可:

  7. layui下select下拉框不显示或没有效果

    Layui会对select.checkbox.radio等原始元素隐藏,从而进行美化修饰处理.但这需要依赖于form组件,所以你必须加载 form,并且执行一个实例.值得注意的是:导航的Hover效果 ...

  8. [OpenGL]点阵显示生日快乐小程序

    刚工作没多久的时候,业余学习了OGL的知识(这是写不好的借口吧), 在某个异性生日的时候写了这个程序. 编译平台: MinGW GCC gcc -o happOK happyOK.c -lglut32 ...

  9. H - the Sum of Cube(水题)

    A range is given, the begin and the end are both integers. You should sum the cube of all the intege ...

  10. vuejs API总结

    vuejs总结: vm指new Vue获取的实例 (1)当dom标签里的值和data里的值绑定后,更改data对应的值可以实时更新标签里的值: 但后续添加的值是无效的(绑定失败). (2)将可以将对象 ...