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)