突然想起一道以前没做出来的题

pandm 2011-07-07 11:50:05
给你一个区间[1...N], 还有若干个操作,定义一个全局变量id = 0(初始值)。
操作的种类是:
(1)I(a, b),插入线段[a,b],a和b是线段的端点,并且定义该线段的编号为id,然后id++
(2)D(n),删除id为n的线段
(3)Q(i,j) 询问有多少条线段覆盖区间[i, j]。如果一个线段的其中一个端点x满足 a < x < b,那么我们才认为该线段覆盖了区间[a, b],或者说该区间包含了该线段。

读入所有的操作,然后根据操作3来输出。


现在还是不会做。
但是有个想法,不知道可不可行。
先建立一棵线段树,对于每个节点,维护一个set,用来存放该结点所代表的区间里包含的所有线段的id集合。
如果要知道区间[i, j]包含的线段数,只要将区间分成若干个对应于线段树节点的小区间,将这些结点的set合并成一个大set,然后看看大set里的id个数就知道区间[i, j]包含的线段数了。


其实我就想知道这题的“标准做法”是什么。
...全文
501 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
超级大笨狼 2011-07-22
  • 打赏
  • 举报
回复
这个还是用线段树做。两个二叉的话,最坏搜索是K*O(LgN)次了。
适合输出覆盖区间的头尾端点,而不适合简单统计数量,有点浪费了。

这个如果用线段树做的话,就在树干节点上存储一下被覆盖的线段count值就可以了。
把最关心的目标作为KPI,面向架构的思路。插入的时候就记录上。
不论有多少覆盖都是logN的。

超级大笨狼 2011-07-22
  • 打赏
  • 举报
回复
在头树里找比头大的,在尾树里找比尾小的,就是覆盖了啊。
「已注销」 2011-07-20
  • 打赏
  • 举报
回复
能否详细一点。二叉树是存储编号还是坐标?在头树里找比头大的,是干嘛用的?
没看明白是怎么回事。
[Quote=引用 6 楼 superdullwolf 的回复:]

CAO,头昏了,出去抽根烟就想到了。
这个问题,就准备两个二叉树,分别存储头和尾编号,就行了。

在头树里找比头大的,在尾树里找比尾小的,O(LgN+LgN)=2*O(LgN)
总体还是O(LgN)的。

不用什么线段树,都是浮云。
[/Quote]
Golden_Shadow 2011-07-14
  • 打赏
  • 举报
回复
建立一个区间树,建立一个表,表中结点存放区间信息(或者用链表,结点存放id和在区间树中的的遍历轨迹,10010111011…)。
pandm 2011-07-10
  • 打赏
  • 举报
回复
对不起,我说错了,所谓“覆盖”的定义应该是,该线段与该区间有除端点以外的重合
zhusizhi007 2011-07-10
  • 打赏
  • 举报
回复
顶顶。。。。这个好象是一维的,不要用到叉积,不难吧
  • 打赏
  • 举报
回复
对于I操作,先不要实际操作,将其保存在数组里,在这个数组中剔除D操作。

剩下的插入线段树中,每个线段树的值就是包含id的个数。记得应用LAZY思想,就是当插入的线段向底下传播时,当遇到某一段,整段都需要累加,那就用一个toAdd暂时保存,先不往下传递,只有遇到查询的边界处于这个整段中间某个部分时,才将toAdd向下传递。

然后再做查询就好了。
autumn1202 2011-07-08
  • 打赏
  • 举报
回复
参考下:

如果N不大的话,直接存就行吧,
Q(i,j)如果只问个数,不考虑是哪几个id的话,
对新线段[a,b],则count[a]++, count[b]++;
对Q[i,j], 只需要把count[i]到count[j]所有count之和

当然可以优化,比如判断下2M与j-i+1的大小,如果2M小就直接逐线段比较。

如果N不定……那就count只存所有线段的端点,并且进行排序,好处是,如果Q很多的话可以提高效率。只有一个Q就没必要了

cfvmario 2011-07-08
  • 打赏
  • 举报
回复
是啊,设有M条线段,直接端点拿出来比较不是才2M次比较么
oo 2011-07-08
  • 打赏
  • 举报
回复
你这样做,极端情况下(M条[1,N]的线段,求区间[1,N-1])是不是要N*M的复杂度?
超级大笨狼 2011-07-08
  • 打赏
  • 举报
回复
CAO,头昏了,出去抽根烟就想到了。
这个问题,就准备两个二叉树,分别存储头和尾编号,就行了。

在头树里找比头大的,在尾树里找比尾小的,O(LgN+LgN)=2*O(LgN)
总体还是O(LgN)的。

不用什么线段树,都是浮云。
超级大笨狼 2011-07-08
  • 打赏
  • 举报
回复
对于每个节点,维护两个set,分别存储线段头尾坐标,而不是一个set存储线段编号比较好。

树的深度是根据插入情况来Build的,不需要的节点不Build,而且,最终只保留有值的叶子,就是“桶”。

而树的树干部分完全是抽象的,无内存消耗。

就是输入一个线段,返回当前全部桶的规模int,所在桶的编号int,中间结果不存储。

33,010

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧