--- tags: python, TOI, 二分搜 --- # ZJ f815. TOI_y21m4_a01遊戲升等 [ZJ f815](https://zerojudge.tw/ShowProblem?problemid=f815) nlist:(1<=ni<=10^7)代表n個士兵目前的等級 nlist.sort()排序後,用第一次二分搜找最小nlist[lft=rgt]滿足cost>c 若第一次二分搜沒找到剛好已知的ni滿足cost=c的升級點,則須再利用找到的位置區間(lft-1,rgt)進行第二次二分搜 或最大的ni仍無法滿足cost>c,則從最大ni逐一+1找 仍是檢查最小cost>c的位置,然後ans = 該位置-1 ## code AC (55ms, 5.7MB) ``` python= # 2021 4 f815: TOI_y21m4_a01遊戲升等 # 可能需要兩次二分搜 # 第一次先找nlist(排序)中最小nlist[rgt]滿足cost>=c # 若某個nlist滿足cost==c,則ans=nlist[mid],break結束 # 若第一次二分搜結果,最後一個nlist[n-1]也不滿足cost>=c,則須從最後一個nlist逐一+1找滿足的ans # 若需要第二次二分搜,從nlist[lft]+1,+2,+3...nlist[rgt]二分搜找最小滿足cost>=c n,c = map(int,input().split()) nlist = [int(x) for x in input().split()] nlist.sort() lft = 0 rgt = n ans = 0 while lft<rgt: mid = (lft+rgt) // 2 cost = 0 for i in range(mid): cost +=(nlist[mid]-nlist[i])**2 if cost==c: ans=nlist[mid] #某個nlist剛好滿足,則ans已得,跳出 break elif cost>c: rgt = mid else: lft = mid+1 # print(lft,rgt) # print(lft,rgt,ans) if not ans: if lft==n: # 若第一次二分搜結果,最後一個nlist[n-1]也不滿足cost>=c,則須從最後一個nlist[-1]+1逐一找找滿足cost>=c的ans cost=0 ans = nlist[-1]+1 while cost<c: cost = 0 for i in range(n): cost +=(ans-nlist[i])**2 ans +=1 ans -=1 else: lftn = nlist[lft-1] rgtn = nlist[rgt] while lftn<rgtn: mid = (lftn+rgtn) // 2 cost = 0 for i in range(lft): cost +=(mid-nlist[i])**2 if cost==c: ans = mid break elif cost>c: rgtn = mid else: lftn = mid+1 # print(lftn,rgtn) if not ans: ans = lftn-1 print(ans) ```