πŸ’» Algorithm/Python

[Python] λ°±μ€€ 2841 μ™Έκ³„μΈμ˜ 기타 μ—°μ£Ό (Stack)

μ„ μ£Ό 2022. 7. 2. 15:13

 

πŸ“Œ 문제

μƒκ·Όμ΄μ˜ μƒμƒμ˜ 친ꡬ 외계인은 손가락을 μˆ˜μ‹­μ–΅κ°œ κ°€μ§€κ³  μžˆλ‹€. μ–΄λŠ λ‚  외계인은 기타가 치고 μ‹Άμ—ˆκ³ , μΈν„°λ„·μ—μ„œ κ°„λ‹¨ν•œ λ©œλ‘œλ””λ₯Ό κ²€μƒ‰ν–ˆλ‹€. 이제 이 기타λ₯Ό 치렀고 ν•œλ‹€.

 

보톡 κΈ°νƒ€λŠ” 1번 쀄뢀터 6번 μ€„κΉŒμ§€ 총 6개의 쀄이 있고, 각 쀄은 P개의 ν”„λ ›μœΌλ‘œ λ‚˜λˆ„μ–΄μ Έ μžˆλ‹€. ν”„λ ›μ˜ λ²ˆν˜Έλ„ 1λ²ˆλΆ€ν„° Pλ²ˆκΉŒμ§€ λ‚˜λˆ„μ–΄μ Έ μžˆλ‹€.

 

λ©œλ‘œλ””λŠ” 음의 연속이고, 각 μŒμ€ μ€„μ—μ„œ ν•΄λ‹Ήν•˜λŠ” 프렛을 λˆ„λ₯΄κ³  쀄을 νŠ•κΈ°λ©΄ μ—°μ£Όν•  수 μžˆλ‹€. 예λ₯Ό λ“€λ©΄, 4번 μ€„μ˜ 8번 프렛을 λˆ„λ₯΄κ³  νŠ•κΈΈ 수 μžˆλ‹€. λ§Œμ•½, μ–΄λ–€ μ€„μ˜ 프렛을 μ—¬λŸ¬ 개 λˆ„λ₯΄κ³  μžˆλ‹€λ©΄, κ°€μž₯ 높은 ν”„λ ›μ˜ 음이 λ°œμƒν•œλ‹€.

 

예λ₯Ό λ“€μ–΄, 3번 μ€„μ˜ 5번 프렛을 이미 λˆ„λ₯΄κ³  μžˆλ‹€κ³  ν•˜μž. μ΄λ•Œ, 7번 프렛을 λˆ„λ₯Έ μŒμ„ μ—°μ£Όν•˜λ €λ©΄, 5번 프렛을 λˆ„λ₯΄λŠ” 손을 λ–Όμ§€ μ•Šκ³  λ‹€λ₯Έ μ†κ°€λ½μœΌλ‘œ 7번 프렛을 λˆ„λ₯΄κ³  쀄을 νŠ•κΈ°λ©΄ λœλ‹€. μ—¬κΈ°μ„œ 2번 ν”„λ ›μ˜ μŒμ„ μ—°μ£Όν•˜λ €κ³  ν•œλ‹€λ©΄, 5번과 7λ²ˆμ„ λˆ„λ₯΄λ˜ 손가락을 λ—€ λ‹€μŒμ— 2번 프렛을 λˆ„λ₯΄κ³  μ—°μ£Όν•΄μ•Ό ν•œλ‹€.

 

μ΄λ ‡κ²Œ μ†κ°€λ½μœΌλ‘œ 프렛을 ν•œ 번 λˆ„λ₯΄κ±°λ‚˜ λ–ΌλŠ” 것을 손가락을 ν•œ 번 μ›€μ§μ˜€λ‹€κ³  ν•œλ‹€. μ–΄λ–€ λ©œλ‘œλ””κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, μ†κ°€λ½μ˜ κ°€μž₯ 적게 μ›€μ§μ΄λŠ” 회수λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

μž…λ ₯

첫째 쀄에 λ©œλ‘œλ””μ— ν¬ν•¨λ˜μ–΄ μžˆλŠ” 음의 수 Nκ³Ό ν•œ 쀄에 μžˆλŠ” ν”„λ ›μ˜ 수 Pκ°€ μ£Όμ–΄μ§„λ‹€. (N ≤ 500,000, 2 ≤ P ≤ 300,000)

 

λ‹€μŒ N개 μ€„μ—λŠ” λ©œλ‘œλ””μ˜ ν•œ μŒμ„ λ‚˜νƒ€λ‚΄λŠ” 두 μ •μˆ˜κ°€ μ£Όμ–΄μ§„λ‹€. 첫 번째 μ •μˆ˜λŠ” μ€„μ˜ 번호이고 두 번째 μ •μˆ˜λŠ” κ·Έ μ€„μ—μ„œ λˆŒλŸ¬μ•Ό ν•˜λŠ” ν”„λ ›μ˜ λ²ˆν˜Έμ΄λ‹€. μž…λ ₯으둜 μ£Όμ–΄μ§„ 음의 μˆœμ„œλŒ€λ‘œ 기타λ₯Ό μ—°μ£Όν•΄μ•Ό ν•œλ‹€.

좜λ ₯

첫째 쀄에 λ©œλ‘œλ””λ₯Ό μ—°μ£Όν•˜λŠ”λ° ν•„μš”ν•œ μ΅œμ†Œ 손가락 μ›€μ§μž„μ„ 좜λ ₯ν•œλ‹€.

예제 μž…λ ₯ 1

5 15
2 8
2 10
2 12
2 10
2 5

예제 좜λ ₯ 1

7

예제 μž…λ ₯ 2

7 15
1 5
2 3
2 5
2 7
2 4
1 5
1 3

예제 좜λ ₯ 2

9

 


 

πŸ“Œ 풀이

import sys
input = sys.stdin.readline

n, p = map(int, input().split())
lines = [[] for _ in range(7)]
cnt = 0

for _ in range(n):
    line, fret = map(int, input().split())
    line = lines[line - 1]

    while line and fret < line[-1]:
        line.pop()
        cnt += 1

    if not line or fret > line[-1]:
        line.append(fret)
        cnt += 1

print(cnt)

 

ν•œ 쀄에 λˆŒλ €μžˆλŠ” ν”„λ › 번호λ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•΄ stack을 μ‚¬μš©ν•˜κ³ , 쀄이 μ—¬λŸ¬κ°œμ΄κΈ° λ•Œλ¬Έμ— stackλ“€μ˜ 리슀트λ₯Ό λ§Œλ“€μ–΄ μ‚¬μš©ν•©λ‹ˆλ‹€.

  • line: ν•΄λ‹Ή 쀄 stack
  • fret: ν˜„μž¬ λˆ„λ₯΄λ €λŠ” ν”„λ › 번호

 

stack μƒνƒœμ˜ 경우의 수λ₯Ό μ‚΄νŽ΄ 보면 크게 μ•„λž˜ 7개의 κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€.

μš°λ¦¬κ°€ μ·¨ν•΄μ•Ό ν•  λ™μž‘μ€ popμ΄κ±°λ‚˜ appendμ΄κ±°λ‚˜ λ‘˜ 쀑 ν•˜λ‚˜μ΄λ―€λ‘œ, pop이 ν•„μš”ν•œ κ²½μš°μ™€ appendκ°€ ν•„μš”ν•œ 경우λ₯Ό μ΄λΆ„λ²•μ μœΌλ‘œ λ‚˜λˆ  보면 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

  • while line and fret < line[-1]
    stack이 μ°¨ 있고 stack top이 λˆ„λ₯΄λ €λŠ” 프렛보닀 큰 번호인 경우 pop
  • if not line or fret > line[-1]
    stack이 λΉ„μ–΄ μžˆκ±°λ‚˜ stack top이 λˆ„λ₯΄λ €λŠ” 프렛보닀 μž‘μ€ 번호인 경우 append