存在以下问题:
一个城市最负盛名的体育俱乐部有N名成员。每个成员都很强大而且漂亮。更确切地说, i 这个俱乐部的成员(成员在他们进入俱乐部时被编号)具有力量S i 和美女B <子> I 的子>。由于这是一个非常有声望的俱乐部,它的成员非常富有,因而非凡的人,所以他们经常非常讨厌彼此。严格地说,我 - 俱乐部成员X先生讨厌 j - 如果S 我 < / sub>≤S j 和B i ≥B j 或者如果S i ≥S j 且B i ≤B j (如果X先生的两个属性都大于Y先生的相应属性,他甚至没有注意到他,另一方面如果他的两处房产都少了,他非常尊重Y先生。
为了庆祝新的2003年,俱乐部的管理部门正计划举办一个派对。然而,他们担心,如果两个互相仇恨的人同时参加聚会,喝了一两杯他们就会开始打架。所以不应该邀请两个互相仇恨的人。另一方面,为了保持俱乐部的声望达到适当的水平,政府希望邀请尽可能多的人。
作为唯一一个不怕触摸电脑的政府,你要编写一个程序,找出邀请参加聚会的人。
的输入 的
*输入文件的第一行包含整数N - 俱乐部的成员数。 (2≤N≤100,000)。接下来N行包含两个数字 - S i 和B i (1≤S < em> i ,B i ≤109)。*
的输出 的
在输出文件的第一行打印可以邀请参加聚会的最大人数。在第二行输出N个整数 - 以任意顺序邀请的成员数。如果存在多个解决方案,则输出任何一个。
样本测试
输入
4 1 1 1 2 2 1 2 2
输出
2 1 4
我正在尝试解决问题但是我的算法的复杂性是O(N ^ 2)并且由于2 <= N <= 100000,因此需要改进算法。 我正在使用具有O(N ^ 2)复杂度的最长增加的子序列动态编程算法来解决该问题。 有人知道如何改进算法吗?
答案 0 :(得分:2)
我认为你的O(n^2)
解决方案甚至不正确,更不用说有效了。如果您有这样的事情:
3
2 2
1 1
3 3
答案是3.然而,经典的LIS算法会给出2。你有这个说明吗?
您可以做的是按S i 排序,并在{<1}}时间在B i 上应用LIS。为此,您可以使用段树或涉及二进制搜索的简单算法。如果您需要更多帮助,请告诉我。
总复杂度为O(n log n)
:此时可以进行排序,LIS也可以。
答案 1 :(得分:2)
这是一个O(n log(n))
答案,其中包含了大量合理的详细信息。
首先按照美丽的上升,力量下降对人进行排序。消除重复。 (在这里明确地,或者通过在下一步中跳过它们来隐式地进行。)
浏览列表。当你走的时候,保持一个平衡的人群,他们可能正在成为最大上升链中的下一个人。每个人都应该存储当前链的长度,以及指向链中其余人的链表的指针。树应按强度分类。
更具体地说,每当你看到一个新人时,找到树中的下一个最弱的人(没人没事),并构建一个三元组(person, length of chain, pointer to chain)
。将人员插入树中。如果树中的下一个更强的人的链不超过当前人,则删除该人。所有这些操作都是O(log(n))
。
当你完成所有人的处理后,树中的最大记录将有一个人在最大人链的末尾,链的长度和指向链表的指针与其余的链中的人。这是你的答案,打印出来。
为了向您展示您的样本数据,以下是您的开始:
4
1 1
1 2
2 1
2 2
这表示:
{person: 1, beauty: 1, strength: 1}
{person: 2, beauty: 2, strength: 1}
{person: 3, beauty: 1, strength: 2}
{person: 4, beauty: 2, strength: 2}
按美容增加排序,然后强度减少(没有重复)得到:
{person: 3, beauty: 1, strength: 2}
{person: 1, beauty: 1, strength: 1}
{person: 4, beauty: 2, strength: 2}
{person: 2, beauty: 2, strength: 1}
为了简化事情,我只用排序集代表树。这不是它应该如何在内存中表示。
插入人3后:
{person: 3, strength: 2, length: 1, next_person: null}
下一个人1个人3。
{person: 1, strength: 1, length: 1, next_person: null}
然后人4来到人1之后。(我把链表写成嵌套数据结构,实际上它应该是一个链表。)
{person: 1, strength: 1, length: 1, next_person: null}
{person: 4, strength: 2, length: 2, next_person: {person: 1, next_person: null}}
然后人2碰到了人。
{person: 2, strength: 1, length: 1, next_person: null}
{person: 4, strength: 2, length: 2, next_person: {person: 1, next_person: null}}
要找到你的答案,请看树的末尾,在第4个人,指向第1个人。你的答案是长度2,然后(从最好到最差)人4然后1。
答案 2 :(得分:1)
如果你想到一个以俱乐部成员为顶点并且“喜欢”为边缘的图形(即如果两个成员不彼此讨厌,那么相应的顶点之间存在边缘),可以重新制定问题如下:
找到子集中所有顶点之间存在边的最大顶点子集。
事实上,所有顶点都有相互边的子集称为Clique或完整的子图。
如果无法利用图表的其他功能,请查找最大集团需要指数时间(请参阅this link)。本文建议使用Bron–Kerbosch algorithm。
在(S,B)
平面中绘制成员,可以看到'like'边缘对应于从12点到3点之间以及6点到9点之间的方向从顶点出来的线条。很容易构造一个这样的边相交的例子,所以很遗憾不是平面图。
不幸的是,“喜欢”关系不是transitive,即A
喜欢B
而B
喜欢C
这并不意味着{ {1}}也喜欢A
(再次,这在C
平面上很容易看到)。
答案 3 :(得分:0)
以下是btilly解决方案如何运作的一些论点:
实际上,respect
和ignore
在某种意义上是对称的
如果A尊重B,那么B忽略A,所以这就足够了
仅查看其中一个关系,例如respect
”。
正如missingno所指出的,respect
关系
是传递意义,如果A尊重B和B尊重C
然后A尊重C(以及B尊重的所有人)。
考虑以下图表:顶点代表成员 从A到B的有向边意味着A尊重B(或等效地,B忽略A)。 在一个人消除重复之后(可以考虑 我们意识到,成员的重量对应于他们的多样性 没有周期(如果A尊重B,则B不可能 通过其他成员尊重A,在某些时候,人们必须这样做 有一个走向错误方向的边缘,即我们有一个 directed acyclic graph
考虑图表中的路径:如果成员A在该路径上, 路径上的所有其他顶点要么被A尊重(进一步'下游') 或被A忽略(进一步'上游')。因此通过图表的任何路径 代表一群彼此都喜欢的成员。
另一方面,如果A和B之间没有路径, 他们彼此讨厌(否则会有例如两者之间的直接边缘 它们)。
所以我们重新解决了问题,找到了最长的路径 一个有向无环图(其中每条边有一个权重)可以完成 一旦我们构建了这样一个图表,就在线性时间内。
剩下的问题是比O(N ^ 2)更快地构造图形 即无需经过所有可能的顶点对。
以下是图形式的btilly示例(箭头表示respect
):
到达顶点A时,我们只需要添加“最近”的邻居 在某种意义上,即不是像我们可以通过他人达到的那些 比如B和C.
这是排序在一个坐标中上升和下降的位置 在另一个坐标中来自:我们添加了边缘之后 A到B我们不会添加从A到D的直接边缘(因为去了 从A到D通过B或C更好),所以我们只需要 看看B的右边和下面的顶点(那些顶点) 不能有B)的优势
答案 4 :(得分:-1)
两个力量和美丽相同的人互相讨厌,力量和美丽的界限非常紧张......