Keep Going

λ°±μ€€ 1744번. 수 λ¬ΆκΈ° λ³Έλ¬Έ

Problem Solving

λ°±μ€€ 1744번. 수 λ¬ΆκΈ°

seon 2024. 7. 1.
λ°˜μ‘ν˜•

πŸ’‘λ¬Έμ œ 뢄석 μš”μ•½

<문제 뢄석>

  • 길이가 N인 μˆ˜μ—΄μ˜ 합을 κ΅¬ν•˜λ €κ³  ν•œλ‹€. 근데 κ·Έ 숫자λ₯Ό λͺ¨λ‘ λ”ν•΄μ„œ κ΅¬ν•˜λŠ”κ²Œ μ•„λ‹ˆμ—μš” !
  • μˆ˜μ—΄μ˜ 두 수λ₯Ό 묢으렀고 ν•΄μš”.
    • μœ„μΉ˜μ— 상관없이 묢을 수 μžˆμ–΄μš”
    • 자기 μžμ‹ κ³Ό 자기 μžμ‹ μ„ 묢을 μˆ˜λŠ” μ—†μ–΄μš”
    • μ–΄λ–€ 수λ₯Ό 묢게 되면 μˆ˜μ—΄μ˜ 합을 ꡬ할 λ•Œ 묢은 μˆ˜λŠ” μ„œλ‘œ κ³±ν•œ λ‹€μŒμ— λ”ν•΄μ§€κ²Œ λ˜μ–΄μš”
  • μˆ˜μ—΄μ˜ λͺ¨λ“  μˆ˜λŠ” 단 ν•œλ²ˆλ§Œ λ¬Άκ±°λ‚˜, μ•„λ‹ˆλ©΄ λ¬Άμ§€ μ•Šμ•„μ•Ό ν•΄μš”.
    • μ•ˆ 묢어도 되고,
    • 묢으렀면 1번만 묢을 수 있고
  • 각 수λ₯Ό 적절히 λ¬Άμ–΄μ„œ κ·Έ μˆ˜μ—΄μ˜ 합이 μ΅œλŒ€κ°€ 되게 ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μ§œμ„Έμš”
  • μˆ˜μ—΄μ— μžˆλŠ” μˆ«μžλŠ” -1000 ≤ ≤ 1000 이닀.
    • 즉, μŒμˆ˜κ°€ μžˆλ‹€λŠ” 것 ! 0이 μžˆλ‹€λŠ” 것 !
  • κ²°κ³Ό 값은 항상 2^31보닀 μž‘λ‹€.

<아이디어>

  • 자 합이 μ΅œλŒ€κ°€ λ‚˜μ˜€λ €κ³  ν•©λ‹ˆλ‹€.
    • ⇒ κ·Έλ¦¬λ””μ˜ λƒ„μƒˆκ°€ λ‚©λ‹ˆλ‹€ ~ 항상 졜고λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•˜λ‹ˆκΉŒμš” ?
  • 수의 μ’…λ₯˜λŠ” 음수, 0, μ–‘μˆ˜μ΄λ‹€.
  • 자 μ–΄λ–»κ²Œ 항상 졜고λ₯Ό λ§Œλ“€κΉŒμš” ?
    • 1 초과 μ–‘μˆ˜
      • 1 초과 μ–‘μˆ˜λ₯Ό λ³΄λŠ” μ΄μœ λŠ” 1*3 = 3 < 1+3 = 4 같은 경우 λ•Œλ¬Έμ΄λ‹€. 1은 κ³±ν–ˆμ„ λ•Œ 더 큰 합을 λ§Œλ“œλŠ”λ° 도움이 λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 1만 λ”°λ‘œ λͺ¨μ•„μ„œ κ²°κ³Ό μˆ˜μ—΄μ— λ„£μ–΄μ£ΌλŠ”κ²Œ 큰 합을 λ§Œλ“œλŠ”λ° 도움이 λœλ‹€. ⭐⭐⭐⭐⭐ (1의 속성)
      • μ–‘μˆ˜λŠ” κ°€μž₯ 큰것듀 2κ°œμ”© λ¬Άμ–΄μ„œ κ³±ν•˜λ©΄ 항상 μ΅œκ³ κ°€ λ˜λŠ”λ° 도움이 되고
      • μ–‘μˆ˜κ°€ 1개 λ‚¨μ•˜μœΌλ©΄ κ·Έλƒ₯ κ²°κ³Ό μˆ˜μ—΄μ— λ”ν•˜λ©΄ 되고
    • 음수
      • 음수인 것듀은 κ°€μž₯ μž‘μ€ 2κ°œμ”© λ¬Άμ–΄μ„œ κ³±ν•˜λ©΄ μ–‘μˆ˜κ°€ λ˜μ–΄μ„œ → 항상 μ΅œκ³ κ°€ λ˜λŠ”λ° 도움이 되고
      • ν˜Ήμ‹œ 음수 ν•˜λ‚˜κ°€ λ‚¨μ•˜κ³  0이 μžˆλ‹€λ©΄
        • κ·Έ λ‘˜μ€ κ³±ν•΄μ£ΌλŠ” 것이 μ’‹κ³ 
      • 음수 ν•˜λ‚˜κ°€ λ‚¨μ•˜λŠ”λ° 0이 μ—†λ‹€λ©΄
        • κ·Έλƒ₯ κ²°κ³Ό μˆ˜μ—΄μ— λ”ν•΄μ€˜μ•Ό ν•˜κ³ 
    • 0
      • 합을 λ§Œλ“œλŠ” 것에 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠκΈ°μ— ꡳ이 κ²°κ³Ό μˆ˜μ—΄μ— 넣어쀄 ν•„μš” μ—†κ³ 
    • 1
      • 1듀을 λͺ¨λ‘ κ²°κ³Ό μˆ˜μ—΄μ— λ„£μ–΄μ£ΌκΈ°
    • κ²°κ³Ό μˆ˜μ—΄μ„ sum ν•œ 것이 μ •λ‹΅ !
  • 핡심은 음수 / 0 / 1 / μ–‘μˆ˜ μ΄λ ‡κ²Œ λΆ„λ¦¬ν•΄μ„œ μ²˜λ¦¬ν•΄μ£ΌλŠ” 것
    • μ•ž λ’€μ—μ„œ 자유둭게 뽑기 μœ„ν•΄ 음수, μ–‘μˆ˜λŠ” deque둜 λ§Œλ“ λ‹€. 0κ³Ό 1은 상관 μ—†μŒ
    • μˆ˜μ—΄μ˜ 숫자λ₯Ό λ°›μ•„μ„œ 각 배열에 λ„£κΈ°
      • if num<0: neg.append(num)
        elif num==0: zero.append(num)
        elif num>1: pos.append(num)
        elif num==1: one.append(num)
    • 음수
      • while neg의 길이가 1보닀 클 λ•Œ κΉŒμ§€
        pop, pop → κ³±ν•˜κΈ° → new_arr.append(묢은 수)
      • negκ°€ 남아 μžˆλ‹€λ©΄(
        • λ§Œμ•½ if zero라면
          new_arr.append(λ‚¨μ•„μžˆλŠ” λ§ˆμ§€λ§‰ ν•˜λ‚˜λ₯Ό λ½‘μ•„μš” neg.pop() * zero.pop())
        • else라면
          new_arr.append(neg.pop())
    • 1초과 μ–‘μˆ˜
      • while pos의 길이가 1보닀 클 λ•Œ κΉŒμ§€
        pop, pop → κ³±ν•˜κΈ° → new_arr.append(묢은 수)
      • posκ°€ 남아 μžˆλ‹€λ©΄ (1개 λ‚¨μ•„μžˆλŠ”κ±°μ£ )
        • new_arr.append(λ‚¨μ•„μžˆλŠ” λ§ˆμ§€λ§‰ ν•˜λ‚˜λ₯Ό λ½‘μ•„μš” λ°°μ—΄.pop())
    • 1
      • while one: res_arr.append(one.pop())
    • print(sum(res_arr))

1 ≤ N < 50

-1000 ≤ 각 μˆ˜μ—΄μ˜ 수 ≤ 1000

μ‹œκ°„ μ œν•œ : 2초

μ—£μ§€ μΌ€μ΄μŠ€

  • λ†“μ³€λ˜ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€
      1 + 1 = 2
    
      2
      1
      1
      ans = 2
    ⇒ 1의 속성을 μƒκ°ν•˜κ²Œ λœλ‹€.
  • -1 + 1 + 2 = 2 3 -1 1 2 ans = 2

μž…μΆœλ ₯

  • μž…λ ₯
  • 4 -1 2 1 3
  • 좜λ ₯
  • 6 # 합이 μ΅œλŒ€κ°€ λ‚˜μ˜€κ²Œ ν–ˆμ„ λ•Œμ˜ μˆ˜μ—΄μ˜ ν•© (항상 2^31보닀 μž‘λ‹€, 음수일 μˆ˜λ„ μžˆλ‹€.)

πŸ’‘μ•Œκ³ λ¦¬μ¦˜ 섀계 (μˆ˜λ„ μ½”λ“œ)

  • μ•ž λ’€μ—μ„œ 자유둭게 뽑기 μœ„ν•΄ 음수, μ–‘μˆ˜λŠ” deque둜 λ§Œλ“ λ‹€. 0κ³Ό 1은 상관 μ—†μŒ
  1. μˆ˜μ—΄μ˜ 숫자λ₯Ό λ°›μ•„μ„œ 각 배열에 λ„£κΈ°
    • if num<0: neg.append(num)
      elif num==0: zero.append(num)
      elif num>1: pos.append(num)
      elif num==1: one.append(num)
  2. 음수
    • while neg의 길이가 1보닀 클 λ•Œ κΉŒμ§€
      pop, pop → κ³±ν•˜κΈ° → new_arr.append(묢은 수)
    • negκ°€ 남아 μžˆλ‹€λ©΄(
      • λ§Œμ•½ if zero라면
        new_arr.append(λ‚¨μ•„μžˆλŠ” λ§ˆμ§€λ§‰ ν•˜λ‚˜λ₯Ό λ½‘μ•„μš” neg.pop() * zero.pop())
      • else라면
        new_arr.append(neg.pop())
  3. 1초과 μ–‘μˆ˜
    • while pos의 길이가 1보닀 클 λ•Œ κΉŒμ§€
      pop, pop → κ³±ν•˜κΈ° → new_arr.append(묢은 수)
    • posκ°€ 남아 μžˆλ‹€λ©΄ (1개 λ‚¨μ•„μžˆλŠ”κ±°μ£ )
      • new_arr.append(λ‚¨μ•„μžˆλŠ” λ§ˆμ§€λ§‰ ν•˜λ‚˜λ₯Ό λ½‘μ•„μš” λ°°μ—΄.pop())
  4. 1
    • while one: res_arr.append(one.pop())
  5. print(sum(res_arr))

πŸ’‘μ½”λ“œ

34088 KB 64 ms
import sys
from collections import deque

n = int(sys.stdin.readline().strip())
neg = deque()
pos = deque()
zero = []
one = []
res_arr = []

for _ in range(n): # O(n)
    num = int(sys.stdin.readline().strip())
    if num<0: neg.append(num)
    elif num==0: zero.append(num)
    elif num>1: pos.append(num)
    elif num==1: one.append(num)

neg = deque(sorted(neg)) # O(nlogn)
while len(neg)>1: # O(n)
    res_arr.append(neg.popleft()*neg.popleft())
if neg: # negκ°€ 1개 λ‚¨μ•„μžˆμŒ
    if zero: # 0이 μžˆλ‹€λ©΄, 0μ΄λž‘ κ³±ν•΄μ„œ λ¬΄νš¨ν™”μ‹œν‚€κΈ°
        res_arr.append(neg.popleft()*zero.pop()) # neg.popleft()
    else:
        res_arr.append(neg.popleft())

pos = deque(sorted(pos, reverse=True)) # O(nlogn)
while len(pos)>1: # O(n)
    res_arr.append(pos.popleft()*pos.popleft())
if pos:
    res_arr.append(pos.popleft())

while one: # O(n)
    res_arr.append(one.pop())

print(sum(res_arr)) # O(n)

πŸ’‘μ‹œκ°„ λ³΅μž‘λ„

O(5n + 2nlogn) = O(nlogn)

⇒ $O(50log50) < 2*10^6$

πŸ’‘ ν‹€λ¦° 이유

  • 1에 λŒ€ν•œ 속성을 κ³ λ €ν•˜μ§€ μ•Šκ³  음수 / 0 / μ–‘μˆ˜ 에 λŒ€ν•΄μ„œλ§Œ 생각함
  • 3 -1 1 2 ans = 1이 λ‚˜μ™”μŒ μ™œλƒν•˜λ©΄ 1의 속성을 κ³ λ €ν•˜μ§€ μ•Šκ³  μ–‘μˆ˜ λ²”μœ„μ— ν¬ν•¨ν•΄μ„œ 2*1 + -1 연산이 λ˜μ—ˆκΈ° λ•Œλ¬Έμ— !

πŸ’‘ ν‹€λ¦° λΆ€λΆ„ μˆ˜μ • or λ‹€λ₯Έ 풀이

  • 1에 λŒ€ν•œ ‘ν•©, κ³±’ 속성을 κ³ λ €ν•΄μ„œ 1을 λ”°λ‘œ λΆ„λ¦¬ν•˜μ—¬ res_arr에 μ „λΆ€ λ”ν•˜κΈ° !
elif num==1: one.append(num)
while one: # O(n)
    res_arr.append(one.pop())

πŸ’‘ λŠλ‚€μ  or κΈ°μ–΅ν•  정보

  • print(sum([])) = 0
  • 1은 λ‹€λ₯Έ μ–‘μˆ˜(k)λž‘ κ³±ν–ˆμ„ λ•Œ k 본인이 되게 λ§Œλ“€κΈ° λ•Œλ¬Έμ— 무쑰건 1*k < 1+k 이닀.
λ°˜μ‘ν˜•