线段树在一些acm题目中经常见到,这种数据结构主要应用在计算几何和地理信息系统中。下图就为一个线段树:

(PS:可能你见过线段树的不同表示方式,但是都大同小异,根据自己的需要来建就行。)

1.线段树基本性质和操作

线段树是一棵二叉树,记为T(a, b),参数a,b表示区间[a,b],其中b-a称为区间的长度,记为L。

线段树T(a,b)也可递归定义为:

若L>1 :  [a, (a+b) div 2]为 T的左儿子;

             [(a+b) div 2,b]为T 的右儿子。 

若L=1 : T为叶子节点。

线段树中的结点一般采取如下数据结构:

struct Node
{
    int   left,right;  //区间左右值
    Node   *leftchild;
    Node   *rightchild;
};

线段树的建立:

Node   *build(int   l ,  int r ) //建立二叉树
{
    Node   *root = new Node;
    root->left = l;
    root->right = r;     //设置结点区间
    root->leftchild = NULL;
    root->rightchild = NULL;

    if ( l +1< r )
    {
       int  mid = (r+l) >>1;
       root->leftchild = build ( l , mid ) ;
       root->rightchild = build ( mid +1 , r) ;
    } 

    return    root;
}

线段树中的线段插入和删除

增加一个cover的域来计算一条线段被覆盖的次数,因此在建立二叉树的时候应顺便把cover置0。

插入一条线段[c,d]:

void  Insert(int  c, int d , Node  *root )
{
       if(c<= root->left&&d>= root->right)
           root-> cover++;
       else
       {
           if(c < (root->left+ root->right)/2 ) Insert (c,d, root->leftchild  );
           if(d > (root->left+ root->right)/2 ) Insert (c,d, root->rightchild  );
       }
} 

删除一条线段[c,d]:

void  Delete (int c , int  d , Node  *root )
{
       if(c<= root->left&&d>= root->right)
           root-> cover= root-> cover-1;
       else
       {
          if(c < (root->left+ root->right)/2 ) Delete ( c,d, root->leftchild  );
          if(d > (root->left+ root->right)/2 ) Delete ( c,d, root->rightchild );
       }
} 

2.线段树的运用

线段树的每个节点上往往都增加了一些其他的域。在这些域中保存了某种动态维护的信息,视不同情况而定。这些域使得线段树具有极大的灵活性,可以适应不同的需求。

例一:

桌子上零散地放着若干个盒子,桌子的后方是一堵墙。如图所示。现在从桌子的前方射来一束平行光, 把盒子的影子投射到了墙上。问影子的总宽度是多少?

这道题目是一个经典的模型。在这里,我们略去某些处理的步骤,直接分析重点问题,可以把题目抽象地描述如下:x轴上有若干条线段,求线段覆盖的总长度,即S1+S2的长度。

2.1最直接的做法:

设线段坐标范围为[min,max]。使用一个下标范围为[min,max-1]的一维数组,其中数组的第i个元素表示[i,i+1]的区间。数组元素初始化全部为0。对于每一条区间为[a,b]的线段,将[a,b]内所有对应的数组元素均设为1。最后统计数组中1的个数即可。

初始     0   0  0  0  0
[1,2]   1   0  0  0  0
[3,5]   1   0  1  1  0
[4,6]   1   0  1  1  1
[5,6]   1   0  1  1  1

其缺点是时间复杂度决定于下标范围的平方,当下标范围很大时([0,10000]),此方法效率太低。

2.2离散化的做法:

基本思想:先把所有端点坐标从小到大排序,将坐标值与其序号一一对应。这样便可以将原先的坐标值转化为序号后,对其应用前一种算法,再将最后结果转化回来得解。该方法对于线段数相对较少的情况有效。

示例:

[10000,22000]   [30300,55000]   [44000,60000]   [55000,60000]

排序得10000,22000,30300,44000,55000,60000

对应得1, 2, 3, 4, 5, 6

然后是 [1,2]     [3,5]    [4,6]    [5,6]

初始     0   0  0  0  0
[1,2]   1   0  0  0  0
[3,5]   1   0  1  1  0
[4,6]   1   0  1  1  1
[5,6]   1   0  1  1  1

10000,22000,30300,44000,55000,60000

1,       2,        3,       4,       5,       6

(22000-10000)+(60000-30300)=41700

此方法的时间复杂度决定于线段数的平方,对于线段数较多的情况此方法效率太低。

2.3使用线段树的做法:

给线段树每个节点增加一个域cover。cover=1表示该结点所对应的区间被完全覆盖,cover=0表示该结点所对应的区间未被完全覆盖。

如下图的线段树,添加线段[1,2][3,5][4,6]

插入算法:

void   Insert(Node  *root , int  a , int  b)
{
    int m;
    if( root ->cover == 0)
    { 

        m = (root->left+ root->right)/2 ;
        if (a == root->left && b == root->right)
            root ->cover =1;
        else if (b <= m)  Insert(root->leftchild , a, b);
        else if (a >= m)  Insert(root->rightchild , a, b);
        else
        {
                Insert(root->leftchild ,a, m);
                Insert(root->rightchild , m, b);
        }
    }
}

统计算法:

int  Count(Node *root)
{
    int  m,n;
    if (root->cover == 1)
            return   (root-> right - root-> left);
    else if (root-> right - root-> left== 1 )return 0;
    m= Count(root->leftchild);
     n= Count(root->rightchild);
    return m+n;
}

 

线段树(segment tree)的更多相关文章

  1. 线段树 Interval Tree

    一.线段树 线段树既是线段也是树,并且是一棵二叉树,每个结点是一条线段,每条线段的左右儿子线段分别是该线段的左半和右半区间,递归定义之后就是一棵线段树. 例题:给定N条线段,{[2, 5], [4, ...

  2. RMQ问题(线段树+ST算法)

    转载自:http://kmplayer.iteye.com/blog/575725 RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ ...

  3. Pascal 线段树 lazy-tag 模板

    先说下我的代码风格(很丑,勿喷) maxn表示最大空间的四倍 tree数组表示求和的线段树 delta表示增减的增量标记 sign表示覆盖的标记 delta,sign实际上都是lazy标志 pushd ...

  4. 【POJ 2528】Mayor’s posters(线段树+离散化)

    题目 给定每张海报的覆盖区间,按顺序覆盖后,最后有几张海报没有被其他海报完全覆盖.离散化处理完区间端点,排序后再给相差大于1的相邻端点之间再加一个点,再排序.线段树,tree[i]表示节点i对应区间是 ...

  5. poj 3264 【线段树】

    此题为入门级线段树 题意:给定Q(1<=Q<=200000)个数A1A2…AQ,多次求任一区间Ai-Aj中最大数和最小数的差 #include<algorithm> #incl ...

  6. [LintCode] Segment Tree Build II 建立线段树之二

    The structure of Segment Tree is a binary tree which each node has two attributes startand end denot ...

  7. [LintCode] Segment Tree Build 建立线段树

    The structure of Segment Tree is a binary tree which each node has two attributes start and end deno ...

  8. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  9. HDU 4107 Gangster Segment Tree线段树

    这道题也有点新意,就是须要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提快速度的目的. 本题过的人非常少,由于大部分都超时了,我严格依照线段树的方法去写.一開始竟然也超时. 然后 ...

随机推荐

  1. 帮助你提高排版技巧的18个 PS 文字特效教程

    Photoshop 文字特效教程对于学习基础的和高级的排版思维有很大的帮助.在这篇文章中,你会发现一组最新发布的文字效果教程.这些高品质的 Photoshop 教程可以帮助你设计出惊人的2D,3D,木 ...

  2. 【poj1091】 跳蚤

    http://poj.org/problem?id=1091 (题目链接) 题意 给出一张卡片,上面有n+1个数,其中最大的数为m,每次可以向前或者向后走卡片上面的步数.问有多少种方案选出n个数组成一 ...

  3. Spring Bean配置

    Spring 是什么 •Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能. •Spring 是一个 IOC(DI) 和 ...

  4. 2014 Super Training #1 B Fix 状压DP

    原题: HDU 3362 http://acm.hdu.edu.cn/showproblem.php?pid=3362 开始准备贪心搞,结果发现太难了,一直都没做出来.后来才知道要用状压DP. 题意: ...

  5. Html 5+

    audio Audio模块用于提供音频的录制和播放功能,可调用系统的麦克风设备进行录音操作,也可调用系统的扬声器设备播放音频文件.通过plus.audio获取音频管理对象. http://www.ht ...

  6. Ubuntu14.04如何备份和恢复系统

    清理Ubuntu14.04的系统的垃圾:先清空回收站,软件升级到最新.Ubuntu系统与Windows系统所采用的文件系统不同, Ubuntu系统在使用或更新过程中不会产生文件碎片和垃圾文件,所以在使 ...

  7. iOS &amp;quot;The sandbox is not in sync with the Podfile.lock&amp;quot;解决方式

    更新Cocoapod之后出现故障: diff: /../Podfile.lock: No such file or directory diff: Manifest.lock: No such fil ...

  8. linux 操作中命令备忘

    1 使用grep 查询关键内容 如果你想在当前目录下 查找"hello,world!"字符串,可以这样: grep -rn "hello,world!" * * ...

  9. zabbix监控mysql性能

    使用zabbix监控mysql的三种方式 1.只是安装agent 2.启用模板监控 3.启用自定义脚本的模板监控 zabbix中默认有mysql的监控模板.默认已经在zabbix2.2及以上的版本中. ...

  10. django之跨表查询及添加记录

    一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);     一本书只应该由一个出版商出 ...