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)

 

posted @ 2018-10-05 01:47  Cloud.9  阅读(253)  评论(0编辑  收藏  举报