应用:

  区间染色

  区间查询

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

使用数组来实现线段树:存储空间为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. String/StringBuilder 类 统计字符串中字符出现的次数

    1.1. 训练描述:[方法.String类] 一.需求说明:定义如下字符串: String str = “javajfiewjavajfiowfjavagkljjava”; 二.请分别定义方法统计出: ...

  2. nexus admin 从文件角度进行密码重置

    \sonatype-work\nexus\conf\security.xml 文件中保存账号密码信息. 打开 vi nexus-2.10.0-02-bundle\sonatype-work\nexus ...

  3. linux删除文件、创建文件

    1.删除文件 rm huahua.txt 2.创建文件 touch huahua.txt

  4. 3.文档视图:从gui分割状态

    为了解决一个类实现所有功能的缺陷,我们把application分为2个部分.一个部分业务逻辑,一个部分视觉渲染和交互.这2个类在学术上被称为document view 或者 model delegat ...

  5. eclipse打包第三方jar的超简便方法

    原帖地址 http://wenku.baidu.com/link?url=0kCBUc-7g4pGgXUrBA2jdCRkrSQmQzaDgGT59TyECAundF8c6R9yxy4EaBN3L8c ...

  6. NETTY4中的BYTEBUF 内存管理

    转 http://iteches.com/archives/65193 Netty4带来一个与众不同的特点是其ByteBuf的重现实现,老实说,java.nio.ByteBuf是我用得很不爽的一个AP ...

  7. wordcount程序实现与测试

    GitHub地址 https://github.com/jiaxuansun/wordcount PSP表格 PSP PSP阶段 预估耗时(分钟) 实际耗时(分钟) Planning 计划 10 5 ...

  8. 关于解决cmd中执行java提示"找不到或无法加载主类"的问题

    昨天学生遇到一个问题:在cmd命令行中,用javac编译java文件可以成功,但是用java执行却提示“找不到或无法加载主类”.现将该问题的原因以及解决办法记录一下. 先理解一下系统变量path和cl ...

  9. C++笔记--指针数组和结构

    指针 类型为T*的变量能保存一个类型T对象的地址 Char c=‘a’:Char * p=& c://保存了c的地址 指针的操作一般都是间接的引用,就是相当于引用指针所指的对象. 0是一个特殊 ...

  10. tcpdump/HTTP协议实践

    tcpdump/HTTP协议实践 客户端: CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAI ...