1. 程式人生 > >cf Social Circles

cf Social Circles

pop 長度 別人 imp 意思 port social 直接 堆排序

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