/**
* 线段树入门
* 问题:已知线段[2,5] [4,6] [0,7];求点2,4,7分别出现了多少次
* 以下代码建立的线段树用链表来保存,且树的叶子结点类似[i,i]
*
* 参考链接:http://hi.baidu.com/semluhiigubbqvq/item/be736a33a8864789f4e4ad18
* @author lijinnan
*/
public class SegmentTreeLearn {
public static void main(String[] args) {
SegmentTree tree = new SegmentTree(0, 7);
int[][] segments = {
{2, 5},
{4, 6},
{0, 7}
};
int[] targets = {2, 4, 7};
for (int i = 0, len = segments.length; i < len; i++) {
int[] segment = segments[i];
tree.insert(segment[0], segment[1]);
}
for(int target : targets) {
System.out.println(target + ":" + tree.caculateExistingTimes(target));
}
}
}
class SegmentTree {
//递归定义的,因此很多操作都是递归实现
private class Segment {
int left;
int right;
int count;
Segment leftChild;
Segment rightChild;
}
private Segment root;
public SegmentTree (int left, int right) {
root = new Segment();
build(root, left, right);
}
public void insert(int left, int right) {
insert(root, left, right);
}
public int caculateExistingTimes(int target) {
return caculateExistingTimes(root, target);
}
//从根节点开始查找叶子结点[target, target],对经过的节点的count求和
private int caculateExistingTimes(Segment root, int target) {
int result = 0;
while( root.left != root.right) {
int rootMid = root.left + (root.right - root.left) / 2;
result += root.count;
if (target <= rootMid) {
root = root.leftChild;
} else if (target > rootMid) {
root = root.rightChild;
}
}
return result;
}
private void build(Segment root, int left, int right) {
root.left = left;
root.right = right;
if (left != right) {
int mid = left + (right - left) / 2;
root.leftChild = new Segment();
root.rightChild = new Segment();
build(root.leftChild, left, mid);
build(root.rightChild, mid + 1, right);
}
}
private void insert(Segment root, int left, int right) {
int rootLeft = root.left;
int rootRight = root.right;
int rootMid = rootLeft + (rootRight - rootLeft) / 2;
//匹配,出现次数加1
if (left == rootLeft && right == rootRight) {
root.count++;
return;
}
if (right <= rootMid) {
insert(root.leftChild, left, right);
} else if (left > rootMid){
insert(root.rightChild, left, right);
} else {
insert(root.leftChild, left, rootMid);
insert(root.rightChild, rootMid + 1, right);
}
}
}
分享到:
相关推荐
线段树是一种高效的数据结构,用于处理区间查询和修改操作,特别适用于动态维护区间信息的问题。它的核心思想是将一个区间划分为更小的子区间,并对这些子区间进行分治,从而实现快速的更新和查询。以下是对线段树的...
权值线段树和主席树入门PPT,权值线段树,顾名思义就是记录权值的线段树,普通的线段树直接以坐标为l,r建树,而权值线段树是以大小来建树,树上寸的信息是该权值的数量,而通过建树时二分从小到大的性质,可以用这...
线段树是一种高效的数据结构,主要用于处理区间查询和更新的问题,比如区间加减、求和、最值等。它的核心思想是将一个大区间分解成若干小的子区间,并存储在二叉树的节点中,从而实现对区间操作的快速响应。 线段树...
线段树是一种高效的数据结构,常用于解决区间查询与修改的问题。在本教程中,我们将深入探讨线段树的基本概念,以及如何使用Java实现线段树来解决实际问题,如POJ3468题目。 首先,理解线段树的核心在于它的分治...
线段树是一种高效的数据结构,用于处理和维护在一维空间中的一系列区间或线段,同时支持动态查询和修改操作。它特别适用于那些需要快速查询区间信息,如求区间和、查找区间内满足条件的元素个数等问题。线段树的核心...
线段树是一种高效的数据结构,常用于解决区间查询与修改的问题。在本篇博文中,我们将深入探讨线段树的概念,以及如何实现懒惰更新(Lazy Propagation)策略,同时结合POJ1823问题进行实战应用。懒惰更新是优化线段...
### 线段树入门级总结 #### 一、初识线段树 ##### 1、线段树的称谓及意义 线段树(Interval Tree),顾名思义,是一种基于区间的特殊数据结构。它能够高效地解决涉及区间查询和修改的问题,尤其适用于动态查询或...
线段树(Segment Tree)是一种数据结构,常用于处理区间查询和更新问题。它通过将一维数组分段,每一段对应一个节点,构建出一棵树形结构,从而支持高效地处理区间范围内的数据操作。在算法领域,线段树是解决动态...
线段树和树状数组是两种在ACM(算法竞赛)和编程中广泛使用的高效数据结构,它们主要用于处理数组上的区间查询和修改操作。这里我们将深入理解这两种数据结构的原理和应用。 首先,线段树是一种能够支持动态维护...
这篇博客“线段树入门学习(兼解HDU1754)”旨在帮助初学者理解线段树的基本概念,并通过解决HDU1754题目来实践其应用。 线段树的核心思想是将一个区间分解成多个子区间,然后对每个子区间进行预处理,存储区间的信息...
7. **实例分析**:文件"XWn线段树-初步学习.doc"可能是对线段树基础概念的介绍,适合初学者入门;"线段树在程序设计中的应用.doc"可能包含线段树在实际问题中的应用案例,如如何用线段树解决竞赛题目;"v79二分法与...
解题的关键在于正确处理区间交集,可以采用线段树或者并查集等数据结构优化算法效率。 **第二题 宴会 (banquet)** 这个题目设定在唐朝背景,涉及数学和规划问题。题目要求在数轴上的点安排宴会,考虑每个官员的...
线段覆盖0.成就 1.目录 C_Cpp STL 分治 动态规划 区间DP 哈希表 图论 最小生成树 最短路 奇思妙想 字符串 字符串匹配 常用技巧 并查集 排序 顺序统计量 搜索 BFS 二分搜索 回溯 数据结构 二叉树 树状数组 树(广义的...
- **用途**:绘制连续的线段。 - **应用场景**:绘制轮廓线、路径等。 **ML,** *MLINE(多线)* - **用途**:绘制两条或多条平行线。 - **应用场景**:表示双车道的道路或其他需要平行线的地方。 **SPL,** *SPLINE...
文件包括以下子文件,每个文件里面包括了一定数量的ppt,doc,c++模板代码,希望对算法...8-线段树 9-树状数组 10-字典树 11-二分图 12-网络流 13-高精度 14-几何 15-自动机 16-DP_01背包 16-DP_树状dp 16-贪心 17-数论
算法竞赛入门经典--训练指南,代码仓库,有四个版本的代码仓库。 《算法竞赛入门经典——训练指南》... 增加线段树部分中两个经典问题的完整代码:快速序列操作I和快速序列操作II 2013-02-28 补全所有159道例题的代码