μ•Œκ³ λ¦¬μ¦˜/이뢄탐색

[λ°±μ€€ 14575 πŸ₯ˆ] 뒀풀이

1eehyunji 2023. 8. 29. 01:27
 

14575번: 뒀풀이

첫째 쀄에 λŒ€νšŒ μ°Έκ°€μžμ˜ 수 Nκ³Ό 술의 μ΄λŸ‰ Tκ°€ μ£Όμ–΄μ§„λ‹€. (1 ≤ N ≤ 1000, 1 ≤ T ≤ 109) λ‘˜μ§Έ 쀄뢀터 N개의 쀄에 걸쳐, 각 μ‚¬λžŒμ— λŒ€ν•œ Li와 Ri값이 μ£Όμ–΄μ§„λ‹€. (1 ≤ Li ≤ Ri ≤ 106)

www.acmicpc.net

문제

λ„ν˜„μ΄λŠ” 이번 λŒ€νšŒλ₯Ό μ€€λΉ„ν•˜λ©΄μ„œ κ±°ν•œ 저녁 λ§Œμ°¬μ„ μ˜ˆμ•½ν–ˆλ‹€.

ν•˜μ§€λ§Œ λͺ¨μ’…μ˜ 이유둜 μš”λ¦¬μ‚¬λ“€μ΄ λͺ¨λ‘ 천ꡭ으둜 λ– λ‚˜λ²„λ ΈκΈ° λ•Œλ¬Έμ—, λ„ν˜„μ΄λŠ” μ–΄μ©” 수 없이 ν‰λ²”ν•œ μ‹ μ΄Œ μˆ μ§‘μ„ 뒀풀이 μž₯μ†Œλ‘œ μ •ν•  μˆ˜λ°–μ— μ—†μ—ˆλ‹€.

λ„ν˜„μ΄λŠ” μš°μ„  각 μ‚¬λžŒμ—κ²Œ μ–΄λŠ 정도 λ§ˆμ‹œλ©΄ 기뢄이 쒋은지(Li)와, μ–΄λŠ 정도 λ§ˆμ‹œλ©΄ νž˜λ“ μ§€(Ri)λ₯Ό λ¬Όμ–΄λ³΄μ•˜λ‹€. 각 μ‚¬λžŒμ€ Li미만의 μˆ μ„ λ§ˆμ‹œλ©΄ 술이 λΆ€μ‘±ν•΄ 기뢄이 μ’‹μ§€ μ•Šκ³ , Riλ₯Ό μ΄ˆκ³Όν•˜λŠ” μˆ μ„ λ§ˆμ‹œλ©΄ 천ꡭ으둜 가버릴 μˆ˜λ„ μžˆλ‹€. λ„ν˜„μ΄λŠ” 각 μ‚¬λžŒλ“€μ—κ²Œ μ λ‹ΉλŸ‰μ”© μˆ μ„ λΆ„λ°°ν•˜λ €κ³  ν•œλ‹€.

그런데 μ‹ μ΄Œ μˆ μ§‘μ΄ 항상 그렇듯이, 사μž₯λ‹˜μ€ λ„ν˜„μ΄μ—κ²Œ Tμ΄μƒμ˜ μˆ μ„ λ°˜λ“œμ‹œ νŒ”μ•„μ€˜μ•Όλ§Œ μ˜ˆμ•½μ„ μž‘μ•„μ£Όκ² λ‹€κ³  엄포λ₯Ό λ†“μ•˜λ‹€. 마침 λ„ν˜„μ΄μ˜ 톡μž₯μ—” μ •ν™•νžˆ T의 μˆ μ„ μ‚΄ 수 μžˆλŠ” κΈˆμ•‘μ΄ λ“€μ–΄ μžˆμ—ˆκ³ , λ„ν˜„μ΄λŠ” μ •ν™•νžˆ T의 μˆ μ„ κ²°μ œν•˜μ˜€λ‹€.

이제 λ„ν˜„μ΄λŠ” λͺ¨λ“  μ‚¬λžŒ iμ—κ²Œ Li이상 Riμ΄ν•˜μ˜ μˆ μ„ μ£Όλ©΄μ„œ, κ·Έ 총합이 μ •ν™•νžˆ Tκ°€ λ˜λ„λ‘ μˆ μ„ λΆ„λ°°ν•˜λ €κ³  ν•œλ‹€. ν•˜μ§€λ§Œ μ•ˆνƒ€κΉκ²Œλ„, μ‚¬λžŒλ“€μ€ μžμ‹ μ˜ μ£ΌλŸ‰μ„ κ³ΌλŒ€ν‰κ°€ν•˜λŠ” κ²½ν–₯이 μžˆλ‹€. 이에 따라 λ„ν˜„μ΄λŠ” S의 값을 μ •ν•˜κ³ , 각 μ‚¬λžŒμ—κ²Œ κ·Έ μ‚¬λžŒμ΄ μ›ν•˜λŠ” 술의 양이 μ–Όλ§ˆμ΄λ˜μ§€ 관계없이 Sμ΄ν•˜μ˜ μˆ λ§Œμ„ μ£Όλ €κ³  ν•œλ‹€. 이제 λ„ν˜„μ΄λŠ” μˆ λ„ κ²°μ œν–ˆκ³ , μ£ΌλŸ‰λ„ μ‘°μ‚¬ν–ˆμœΌλ―€λ‘œ,

  1. λͺ¨λ“  μ‚¬λžŒ iκ°€ Li이상 Riμ΄ν•˜μ˜ μˆ μ„ λ°›μœΌλ©΄μ„œ,
  2. λͺ¨λ“  μ‚¬λžŒμ΄ 받은 술의 총합이 μ •ν™•νžˆ Tκ°€ 되고,
  3. μ–΄λ–€ μ‚¬λžŒλ„ Sλ₯Ό μ΄ˆκ³Όν•˜λŠ” μˆ μ€ λ°›μ§€ μ•Šκ²Œ ν•  수 μžˆλŠ”,

κ·ΈλŸ¬ν•œ Sκ°’λ§Œ κ²°μ •ν•˜λ©΄ λœλ‹€.

λ„ν˜„μ΄λ₯Ό 도와 쑰건을 λ§Œμ‘±ν•˜λŠ” S값을 찾아주도둝 ν•˜μž.

λ§Œμ•½ 그런 값이 μ—¬λŸ¬ 개라면, λ„ν˜„μ΄λŠ” κ·Έ 쀑 κ°€μž₯ μž‘μ€ 값을 μ°Ύκ³  μ‹Άλ‹€.

μž…λ ₯

첫째 쀄에 λŒ€νšŒ μ°Έκ°€μžμ˜ 수 Nκ³Ό 술의 μ΄λŸ‰ Tκ°€ μ£Όμ–΄μ§„λ‹€. (1 ≤ N ≤ 1000, 1 ≤ T ≤ 109)

λ‘˜μ§Έ 쀄뢀터 N개의 쀄에 걸쳐, 각 μ‚¬λžŒμ— λŒ€ν•œ Li와 Ri값이 μ£Όμ–΄μ§„λ‹€. (1 ≤ Li ≤ Ri ≤ 106)

좜λ ₯

λ§Œμ•½ S의 κ°’κ³ΌλŠ” 관계없이 항상 λΆˆκ°€λŠ₯ν•˜λ‹€λ©΄ 첫째 쀄에 -1λ§Œμ„ 좜λ ₯ν•œλ‹€.

문제의 쑰건을 λ§Œμ‘±ν•˜λŠ” S값이 μ‘΄μž¬ν•œλ‹€λ©΄ κ°€μž₯ μž‘μ€ κ°’ ν•˜λ‚˜λ₯Ό 좜λ ₯ν•œλ‹€.

 

문제 풀이

import sys

n,t=map(int, sys.stdin.readline().strip().split(' '))

L=[]
R=[]
for _ in range(n):
    l,r=map(int, sys.stdin.readline().strip().split(' '))
    L.append(l)
    R.append(r)

# μ΅œμ†Œ μ£ΌλŸ‰μ„ λͺ¨λ‘ λ”ν–ˆλŠ”λ° t보닀 크닀면 λΆˆκ°€λŠ₯ν•œ 경우
if sum(L)>t:
    print(-1)
    sys.exit(0)
# μ΅œλŒ€ μ£ΌλŸ‰μ„ λͺ¨λ‘ λ”ν–ˆλŠ”λ° t보닀 μž‘λ‹€λ©΄ λΆˆκ°€λŠ₯ν•œ 경우
if sum(R)<t:
    print(-1)
    sys.exit(0)

def possible(mid):
    more=0
    min_adding=0
    for l,r in list(zip(L,R)):
        min_adding+=l
        if l<=mid<=r:
            more+=(mid-l)
        elif mid>r:
            more+=(r-l)
    if more>=(t-min_adding):
        return True
    else:
        return False

startS=max(L)
endS=max(R)
mid=(startS+endS)//2

while startS<=endS:
    mid = (startS + endS) // 2
    # Sκ°€ mid일 λ•Œ κ°€λŠ₯ν•œκ°€?
    if possible(mid):
        # κ°€λŠ₯ν•  경우 -> mid 값을 더 쀄일 수 μ—†λŠ”μ§€?
        endS=mid-1
    else:
        # λΆˆκ°€λŠ₯ν•  경우 -> mid 값을 더 λŠ˜λ €λ„ λΆˆκ°€λŠ₯ν•œκ°€?
        startS=mid+1

print(mid)
  • μ‚¬λžŒλ“€μ˜ μ΅œμ†Œ μ£ΌλŸ‰(Li)을 λͺ¨λ‘ λ”ν•΄μ„œ T보닀 클 경우 λΆˆκ°€λŠ₯ν•œ κ²½μš°μ΄λ―€λ‘œ -1을 좜λ ₯ν•˜κ³  ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•œλ‹€.
  • μ‚¬λžŒλ“€μ˜ μ΅œλŒ€ μ£ΌλŸ‰(Ri)을 λͺ¨λ‘ λ”ν•΄μ„œ T보닀 μž‘μ„ 경우 λΆˆκ°€λŠ₯ν•œ κ²½μš°μ΄λ―€λ‘œ -1을 좜λ ₯ν•˜κ³  ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•œλ‹€.
  • μœ„ 경우λ₯Ό λͺ¨λ‘ 톡과할 경우 이뢄탐색을 μ΄μš©ν•΄μ„œ μ μ ˆν•œ S값을 μ°ΎλŠ”λ‹€.
    • S값이 μ–΄λ–€ μ‚¬λžŒμ˜ μ΅œμ†Œ μ£ΌλŸ‰λ³΄λ‹€ μž‘μ„ 경우, ν•΄λ‹Ή μ‚¬λžŒμ˜ μ£ΌλŸ‰ λ²”μœ„λ₯Ό λ§Œμ‘±ν•  수 μ—†κΈ° λ•Œλ¬Έμ—, S값은 μ΅œμ†Œ μ£ΌλŸ‰λ“€ 쀑 μ΅œλŒ“κ°’ 이상이어야 ν•œλ‹€.
    • S값이 μ΅œλŒ€ μ£ΌλŸ‰λ“€μ˜ μ΅œλŒ“κ°’λ³΄λ‹€ μ»€μ§€λŠ” κ²½μš°λΆ€ν„°λŠ” μ‚¬λžŒλ“€μ˜ μ£ΌλŸ‰ λ²”μœ„λ₯Ό λͺ¨λ‘ λ§Œμ‘±ν•˜κ²Œ λ˜λ―€λ‘œ S 값이 더 컀지더라도 κ²°κ³ΌλŠ” λ˜‘κ°™λ‹€. 
    • κ·Έλž˜μ„œ Sκ°’ 이뢄 탐색을 μœ„ν•œ startS와 endSλ₯Ό 각각 μ΅œμ†Œ μ£ΌλŸ‰λ“€μ˜ μ΅œλŒ“κ°’, μ΅œλŒ€ μ£ΌλŸ‰λ“€μ˜ μ΅œλŒ“κ°’μœΌλ‘œ 두고 이뢄탐색을 κ΅¬ν˜„ν–ˆλ‹€.
    • μ–΄λ–€ S 값이 λͺ¨λ“  μ‚¬λžŒλ“€μ˜ λ²”μœ„λ₯Ό λ§Œμ‘±ν•˜λ©΄μ„œ, μ‚¬λžŒλ“€μ΄ λ§ˆμ‹  술의 μ΄λŸ‰μ΄ Tκ°€ 될 수 μžˆλŠ” κ²½μš°μΈμ§€λŠ” λ‹€μŒκ³Ό 같은 κ³Όμ •μœΌλ‘œ ν™•μΈν•œλ‹€.
      • λ¨Όμ € λͺ¨λ“  μ‚¬λžŒλ“€μ΄ μ΅œμ†Œ μ£ΌλŸ‰λ§ŒνΌλ§Œ λ§ˆμ…¨λ‹€κ³  κ°€μ •ν•œλ‹€.
      • 그리고 각 μ‚¬λžŒλ³„λ‘œ μ£ΌλŸ‰ λ²”μœ„μ™€ S값을 κ³ λ €ν•΄μ„œ μ–Όλ§ˆλ‚˜ 더 λ§ˆμ‹€ 수 μžˆλŠ”μ§€ νŒŒμ•…ν•œλ‹€.
        • S값이 Li와 Ri μ‚¬μ΄μ˜ 값이라면 S-Li만큼 더 λ§ˆμ‹€ 수 있고, S값이 Ri보닀 크닀면 Ri-Li만큼 더 λ§ˆμ‹€ 수 μžˆλ‹€.
      • 이 νŒŒμ•…ν•œ 값듀은 λ³€μˆ˜ more에 μ €μž₯해두고 moreκ°€ μ΄λŸ‰ Tμ—μ„œ μ΅œμ†Œ μ£ΌλŸ‰μ„ λΊ€ 값보닀 크닀면 κ°€λŠ₯ν•œ 경우라고 νŒλ‹¨ν•œλ‹€.
      • κ°€λŠ₯ν•œ 경우라면 endS=mid-1둜 더 μž‘μ€ S값이 κ°€λŠ₯ν•œμ§€ νŒŒμ•…ν•˜κ³ , λΆˆκ°€λŠ₯ν•˜λ‹€λ©΄ startS=mid+1둜 더 큰 Sκ°’μœΌλ‘œλŠ” κ°€λŠ₯ν•œμ§€ νŒŒμ•…ν•œλ‹€.
      • μ΄λŸ¬ν•œ 과정을 λ°˜λ³΅ν•˜λ©΄μ„œ κ°€μž₯ μž‘μ€ S값을 μ°ΎλŠ”λ‹€.