`
kmplayer
  • 浏览: 512525 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

线段树

 
阅读更多
线段树的构造思想
线段树是一棵二叉树,树中的每一个结点表示了一个区间[a,b]。每一个叶子节点表示了一个单位区间。对于每一个非叶结点所表示的结点[a,b],其左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2,b]。
例如:

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

例1:求覆盖线段的总长度
      [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]

线段树做法:







例2:http://acm.pku.edu.cn/JudgeOnline/problem?id=2528
题意:贴海报,输出可以看到的个数.

//贴海报,输出没有被覆盖的个数
//可以改成cpp试试
#include<stdio.h>
struct node
{
    int l,r; //左右孩子的编号
    int st,mi,en;
    int id;
};  // 线段树简单一维
const int maxN = 50000002; //线段树的节点个数
const int maxL = 10000020; //台阶的宽度上限

node segment_tree[maxN]; //保存着线段树的所有节点
#define tree segment_tree
int root, ptr;
void insert(int cr, int start, int end, int color) //插入到指定区域,同时初始化沿途的所有节点
{
    if(start >= end) //不符合输入要求
        return;
    if(tree[cr].st == start && tree[cr].en == end) //输入区间正好等于节点的表示区间
    {
        tree[cr].id = color; //这个区间属于该海报
        return;
    }
    int mid = (tree[cr].st + tree[cr].en) / 2;
    if(tree[cr].l == 0) //意味着还没有初始化孩子结点
    {
        //ptr代表节点的编号
        tree[cr].l = ptr++;
        tree[tree[cr].l].l = tree[tree[cr].l].r = 0;
        tree[tree[cr].l].id = -1;
        tree[tree[cr].l].st = tree[cr].st, //这里对左右孩子的范围进行初始化
        tree[tree[cr].l].en = mid;
    }
    if(tree[cr].r == 0)
    {
        tree[cr].r = ptr++;
        tree[tree[cr].r].l = tree[tree[cr].r].r = 0;
        tree[tree[cr].r].id = -1;
        tree[tree[cr].r].st = mid,
        tree[tree[cr].r].en = tree[cr].en;
    }

    if(tree[cr].id != 0) //之后的子区间肯定都属于该海报
    {
        tree[tree[cr].l].id = tree[tree[cr].r].id = tree[cr].id;
        tree[cr].id = 0;
    }

    if(start >= mid){
        insert(tree[cr].r, start, end, color);
        return;
    }
    if(end <= mid){
        insert(tree[cr].l, start, end, color);
        return;
    }
    insert(tree[cr].l, start, mid, color);
    insert(tree[cr].r, mid, end, color);
}


char exist[10001];
void trail(int cr) //统计可以看见的节点编号
{
    if(cr == 0 || tree[cr].id == -1)
        return;
    exist[tree[cr].id] = 1; //id不为0,意味着只有它可见,但之后的节点都看不见了.
    if(tree[cr].id != 0) //不为0意味着后面的区域都要被覆盖.
        return;
    trail(tree[cr].l);
    trail(tree[cr].r);
}

//初始化跟节点
void init()
{
    root = 1;
    tree[root].l = tree[root].r = tree[root].id = 0;
    tree[root].st = 1, tree[root].en = maxL, tree[root].mi = (1 + maxL)/2;
    ptr = 2;
}

int main()
{
    int test,n,i,l,r;
    scanf("%d", &test);
    while(test--)
    {
        init();
        scanf("%d",&n);
        for(i = 1; i <= n; i++)
        {
            scanf("%d%d",&l,&r);
            insert(1, l, r+1, i); //从根节点开始插入
        }
        for(i = 1; i <= n; i++)
            exist[i] = 0;
        trail(1);
        int ans = 0;
        for(i = 1; i <= n; i++)
            if(exist[i])
                ans++;
        printf("%d\n",ans);
    }
    return 0;
}



  • 大小: 32.9 KB
  • 大小: 48.4 KB
  • 大小: 51.1 KB
  • 大小: 47.3 KB
分享到:
评论

相关推荐

    线段树的一种实现

    线段树是一种高效的数据结构,常用于处理区间查询与更新问题。它的核心思想是将一个一维数组通过分治策略转化为一棵二叉树,每个节点代表一个区间的值,这棵树通常具有平衡性质,比如平衡二叉搜索树的特性。线段树在...

    pascal区间线段树

    **Pascal 区间线段树详解** 线段树(Segment Tree)是一种数据结构,用于高效地处理数组或序列上的区间查询与修改操作。在Pascal编程语言中,我们可以使用记录(Record)类型来实现一个区间线段树。以下是基于给定...

    线段树,数据结构的选择与算法效率

    ### 线段树:数据结构的选择与算法效率 #### 引言 在程序设计领域,数据结构的选择和算法的设计是解决复杂问题的关键。合理的数据结构不仅能够简化问题的复杂度,还能显著提高算法的执行效率。《线段树,数据结构...

    acm程序设计竞赛_培训_线段树

    浙江大学_acm程序设计竞赛_培训_线段树浙江大学_acm程序设计竞赛_培训_线段树浙江大学_acm程序设计竞赛_培训_线段树浙江大学_acm程序设计竞赛_培训_线段树浙江大学_acm程序设计竞赛_培训_线段树浙江大学_acm程序设计...

    轻松学习线段树 进来看看

    线段树是一种高效的数据结构,用于处理区间查询和修改操作,特别适用于动态维护区间信息的问题。它的核心思想是将一个区间划分为更小的子区间,并对这些子区间进行分治,从而实现快速的更新和查询。以下是对线段树的...

    几道经典线段树题目及代码

    线段树,作为一种高效的数据结构,广泛应用于计算机科学和算法设计中,特别是在处理区间查询和更新问题时。它能够以O(logN)的时间复杂度完成区间内的查询与修改操作,大大提高了程序的运行效率。本资源包含了一些...

    线段树完整版

    ### 线段树知识点详解 #### 一、线段树基本概念与应用 线段树是一种二叉树数据结构,常用于处理区间查询或区间更新的问题。它将一个线性序列分割成多个不连续的段,每一个节点代表一个区间,并且通过递归的方式将...

    线段树六题

    线段树是一种非常有效的数据结构,主要用于解决区间查询和更新的问题,常用于算法竞赛和实际应用中的问题求解。接下来,我们将详细探讨“线段树六题”中各个题目的相关知识点。 ### 1. PKU2352 star2 校门外的树 **...

    线段树 二分 统计 ACM

    线段树是一种数据结构,主要用于高效地处理区间查询与修改问题。在计算机科学,特别是算法竞赛(如ACM/ICPC)中,线段树是一个非常重要的工具,它能够帮助我们快速解决涉及区间操作的问题,比如求区间和、查找区间...

    线段树.pdf

    线段树是一种高效的二叉树形数据结构,用于存储区间或线段,并允许快速查询其构成的区间内的信息。它可以用于解决诸如区间求和、区间最值等区间查询问题,并支持单点更新和成段更新等操作。 首先,线段树的实现基础...

    线段树高级数据结构实现

    ### 线段树高级数据结构实现:点更新 #### 一、线段树简介 线段树是一种高效的数据结构,常用于处理区间查询或区间更新的问题。它将一个线性序列分割成多个部分,每个节点代表一个区间的统计信息(如最大值、...

    线段树——在ACM中制胜的法宝

    线段树——在ACM中制胜的法宝 线段树是一种非常重要的数据结构,广泛应用于算法竞赛(ACM)和实际编程中。线段树可以高效地解决许多问题,如区间查找、区间更新、区间统计等。但是,对于线段树的理解和应用,需要对...

    acm线段树基本

    ACM线段树基本 线段树是一种常用的数据结构,广泛应用于算法竞赛编程和数据结构设计中。它是一种树形结构,能够高效地进行区间查询和修改操作。 线段树的基本概念 线段树是一棵二叉树,每个结点表示一个区间。...

    剖析线段树与矩形切割

    线段树和矩形切割是数据结构和算法领域中的重要工具,主要用于处理动态查询和更新问题,以及在二维空间中的几何问题。这两种方法在解决复杂问题时展现了强大的灵活性和高效性,尤其在处理大规模数据时。 线段树是一...

    线段树PPT两个,所有常规用法

    线段树是一种高效的数据结构,常用于处理区间查询与修改问题。在计算机科学特别是算法竞赛(ACM)中,线段树是解决动态区间问题的重要工具。本篇将详细讲解线段树的基本概念、构建方法、操作类型以及常见应用。 ...

    完全版线段树

    线段树是一种高效的数据结构,常用于处理动态的区间查询和修改问题。在这个“完全版线段树”中,作者NotOnlySuccess分享了他对线段树的理解和优化,旨在为ACMer(编程竞赛爱好者)提供更好的学习资源。下面将详细...

    线段树学习步骤

    线段树是一种高效的数据结构,常用于处理区间查询和区间更新的问题。它的核心思想是将一个数组分成多个连续的子区间,并对每个子区间维护一个代表性的信息,从而实现快速查询和更新。以下是对线段树学习步骤的详细...

    线段树及其应用(PPT)

    线段树是一种高效的数据结构,尤其适用于处理区间查询与更新问题。它在信息学、数据结构和OI(奥林匹克信息学)领域中具有广泛的应用。线段树的核心思想是通过二分的思想将一个大区间划分为若干小的子区间,每个节点...

    线段树 数据结构 数 统计 RMQ

    线段树是一种高效的数据结构,主要用于处理区间查询和更新操作,尤其在解决区间最小值、最大值、求和等统计问题以及动态维护区间状态时表现出色。本文将深入解析线段树的基本概念、构建原理、关键操作以及在RMQ...

Global site tag (gtag.js) - Google Analytics