cf Social Circles

Posted waldenlake

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf Social Circles相关的知识,希望对你有一定的参考价值。

http://codeforces.com/contest/1060/problem/D

 

贪心啊!!!!

既然两个a的左和b的右在重叠,那就尽量让重叠最多。

排序后用贪心不就ok。排序n*log(n)+最后o(n)求answer

因为:可以用很多张桌子!!

太坑了,读题想当然觉得是一张桌子,就带来了一个新问题,难度增大,比较有意思。

就是加一个限制,只能用一张桌子

这样a的左和b的右重叠后,如果还有别人,b的左就不能和a的右重叠了!你要防止有这种抱圈的现象,才能让大家形成一个大圈。

一个暴力的方法就是对左手长度排序,记录每个长度属于哪个人。右手长度也一样。

然后对最长的左手(从最短开始也一样道理)去找和他不用集合的人的最长的右手,然后将之标记并查集为一起。可这样寻找过程的复杂度是n^2的。

至于加速,就要用堆排序了,当前最长左手和最长右手在不同集合,直接pop,如果相同,就去找右手集里不用集合的前提下最大的,这样就是直到pop出不同的,再把刚才额外pop的相同集合左手push回去。

是不是很麻烦??其实不是,因为有一个观察,你每次把两个不同集合的左右手合并,然后把剩下的两人的左右说当作一个人的,并改成其中某个人的id,那么当前heap里留下的哥们里,只有1个和你同集,因为坐在中间的哥们都删掉了。

那么当最大的右手和最大的左手同集时,次之的右手必然和他不同,你最多pop两次,这样就下降到n*log(n)了,就能搞定了!

code:

import heapq
n=int(input())
fa=[i for i in range(n)]
def ufind(i):
    global fa
    if i==fa[i]:
        return i
    fa[i]!=ufind(fa[i])
    return fa[i]
def union(i,j):
    global fa
    fi=ufind(i)
    fa[fi]=j

ls=[]
rs=[]
for i in range(n):
    l,r=[int(x) for x in input().split()]
    ls.append((l,i))
    rs.append((r,i))
heapq.heapify(ls)
heapq.heapify(rs)

ans=n
if n==1:
    print(max(ls[0][0],rs[0][0])+1)
    quit()
for i in range(n):
    ll=heapq.heappop(ls)
    if ufind(rs[0][1])!=ufind(ll[1]):
        rr=heapq.heappop(rs)
        union([ll[1]],rr[1])
    else:
        tem=heapq.heappop(rs)
        rr=heapq.heappop(rs)
        union(ll[1],rr[1])
        heapq.heappush(rs,tem)
    ans+=max(ll[0],rr[0])
print(ans)

 

以上是关于cf Social Circles的主要内容,如果未能解决你的问题,请参考以下文章

codeforces_D. Social Circles

Codeforces Round #513 D - Social Circles(贪心)

[CF963E]Circles of Waiting[高斯消元网格图优化+期望]

powershell 来自http://social.technet.microsoft.com/Forums/en-US/9cc5b5c6-e728-4f48-af6c-00cf8be3d4ba/p

如何从后台弹出片段

[LeetCode] 547. Friend Circles 朋友圈