폴더 분리
This commit is contained in:
46
workbook_8708/silver/10431-s5.py
Normal file
46
workbook_8708/silver/10431-s5.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# 줄세우기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def test(students):
|
||||
line = [float('inf')] * 20
|
||||
count = 0
|
||||
|
||||
for i, s in enumerate(students):
|
||||
now_idx = 0
|
||||
while 1:
|
||||
if line[now_idx] > s:
|
||||
break
|
||||
now_idx += 1
|
||||
for j in range(i-1, now_idx-1, -1):
|
||||
line[j+1] = line[j]
|
||||
count += 1
|
||||
line[now_idx] = s
|
||||
|
||||
return count
|
||||
|
||||
def solution():
|
||||
p = int(input().rstrip())
|
||||
|
||||
for _ in range(p):
|
||||
test_case = list(map(int, input().rstrip().split()))
|
||||
print(test_case[0], test(test_case[1:]))
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 33분
|
||||
|
||||
시간 복잡도: 새로운 학생이 line에 들어올때마다 원래 있던 모든 학생이 움직이는 경우가 최대이므로
|
||||
학생 수를 n이라고 하면 학생 당 (n-1), (n-2),... 0 이므로 O(n^2)인데, 이 문제는 20명 고정이므로
|
||||
19*20/2 = 190 이다.
|
||||
|
||||
해설: 기본 line을 float('inf')로 세팅함으로써 사람이 없는 경우는 맨 뒤에 두고 없는 사람 취급을 한다.
|
||||
세팅 후 순서대로 한명씩 line에 넣는데 이때 나보다 큰 가장 앞에 있는 사람을 찾아야 하기 때문에
|
||||
그냥 맨 처음부터 보다가 나보다 큰 사람이 있으면 그 index에 내가 서고, 뒤에 있는 사람들을
|
||||
한 칸씩 뒤로 밀면 된다. 뒤로 밀때는 지금까지 line에 있는 사람 수에서 내가 들어가야할 index까지
|
||||
거꾸로 오면서 한 칸씩 뒤로 밀면 된다. 이때 count+1을 해주고 결과값 count를 반환하고 출력.
|
||||
"""
|
||||
40
workbook_8708/silver/1138-s2.py
Normal file
40
workbook_8708/silver/1138-s2.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# 한 줄로 서기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
blank = [i for i in range(n)]
|
||||
|
||||
info = list(map(int, input().rstrip().split()))
|
||||
|
||||
result = [0] * n
|
||||
for i in range(n):
|
||||
result[blank[info[i]]] = i+1
|
||||
blank.pop(info[i])
|
||||
|
||||
print(*result)
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분
|
||||
|
||||
시간 복잡도: 원하는 것을 pop하는 것은 O(n)이 걸릴 수 있고, 그것을 n번 하므로 O(n^2)이다.
|
||||
blank의 칸을 dict로 관리하면 O(n)으로 가능할 것 같다.
|
||||
|
||||
해설: 본인보다 키가 큰 사람이 왼쪽에 몇 명인지 안다는 것은 본인보다 모두가 키가 큰 구성에서는 몇 등인지 안다는 것이다.
|
||||
그렇기 때문에 키가 1인 사람부터 등수를 구할 수 있고, 구한다음에는 1을 배제하고 2가 키가 제일 작은 구성에서 몇 등인지
|
||||
구하는 방식으로 진행하면 된다.
|
||||
이때, 이미 1이 차지한 등수를 제외하고 남은 칸들 중에 나온 등수대로 넣으면 된다.
|
||||
따라서 빈 자리를 의미하는 blank 리스트에서 남는 칸들을 확인할 수 있고, info+1이 본인의 등수이지만 blank는 0부터 시작하므로
|
||||
그냥 blank[info]를 하면 본인이 차지해야하는 칸이 나온다.
|
||||
그 후 blank에서 차지한 칸을 지워주면 나오는 등수대로 잘 들어갈 수 있다.
|
||||
"""
|
||||
62
workbook_8708/silver/11501-s2.py
Normal file
62
workbook_8708/silver/11501-s2.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# 주식
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def calculate_revenue(n, prices):
|
||||
total = 0
|
||||
q = deque([prices[0]])
|
||||
up = 0
|
||||
if prices[0] <= prices[1]:
|
||||
up = 1
|
||||
else:
|
||||
up = 0
|
||||
|
||||
for i in range(1, n):
|
||||
if len(q) != 0 and i == n-1 and prices[i] >= q[-1]:
|
||||
high = q.pop() if i != n-1 else prices[i]
|
||||
while len(q) >= 1 and q[0] > high:
|
||||
q.popleft()
|
||||
while len(q) >= 1:
|
||||
total += (high-q.pop())
|
||||
|
||||
if not up:
|
||||
if len(q) != 0 and prices[i] > q[-1]:
|
||||
up = 1
|
||||
q.append(prices[i])
|
||||
continue
|
||||
|
||||
if len(q) != 0 and (prices[i] < q[-1] or i == n-1):
|
||||
high = q.pop() if i != n-1 else prices[i]
|
||||
while len(q) >= 1 and q[0] > high:
|
||||
q.popleft()
|
||||
while len(q) >= 1:
|
||||
total += (high-q.pop())
|
||||
up = 0
|
||||
q.append(prices[i])
|
||||
|
||||
return total
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
|
||||
for _ in range(t):
|
||||
n = int(input().rstrip())
|
||||
prices = list(map(int, input().rstrip().split()))
|
||||
print(calculate_revenue(n, prices))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간:
|
||||
|
||||
시간 복잡도:
|
||||
|
||||
해설:
|
||||
"""
|
||||
72
workbook_8708/silver/11723-s5.py
Normal file
72
workbook_8708/silver/11723-s5.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# 집합
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
s = {}
|
||||
all_s = {i: 1 for i in range(1,21)}
|
||||
|
||||
def add(x):
|
||||
if s.get(x, None) != None:
|
||||
return
|
||||
s[x] = 1
|
||||
|
||||
def remove(x):
|
||||
if s.get(x, None) == None:
|
||||
return
|
||||
s.pop(x)
|
||||
|
||||
def check(x):
|
||||
print(s.get(x, 0))
|
||||
|
||||
def toggle(x):
|
||||
if s.get(x, None) != None:
|
||||
s.pop(x)
|
||||
else:
|
||||
s[x] = 1
|
||||
|
||||
def all():
|
||||
global s
|
||||
s = all_s.copy()
|
||||
|
||||
def empty():
|
||||
global s
|
||||
s = {}
|
||||
|
||||
def excute(exc, *arg):
|
||||
if exc == "add":
|
||||
add(arg[0])
|
||||
elif exc == "remove":
|
||||
remove(arg[0])
|
||||
elif exc == "check":
|
||||
check(arg[0])
|
||||
elif exc == "toggle":
|
||||
toggle(arg[0])
|
||||
elif exc == "all":
|
||||
all()
|
||||
elif exc == "empty":
|
||||
empty()
|
||||
else:
|
||||
return
|
||||
|
||||
def solution():
|
||||
global s
|
||||
m = int(input())
|
||||
|
||||
for _ in range(m):
|
||||
q = input().rstrip().split()
|
||||
exc, arg = q[0], list(map(int, q[1:]))
|
||||
excute(exc, *arg)
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 30분(연산 함수를 OCP로 어떻게 할지 고민하다가 그냥 했는데 나중에는 디스패치 패턴 써야겠다..)
|
||||
|
||||
시간복잡도: O(m)
|
||||
|
||||
해설: set을 써도 되긴 하는데 너무 문제가 set 그 자체라서 dictionary로 구현해보았다.
|
||||
x가 1에서 20까지니까 비트마스크 20자리로 해도 가능하다고 한다.
|
||||
"""
|
||||
62
workbook_8708/silver/1205-s4.py
Normal file
62
workbook_8708/silver/1205-s4.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# 등수 구하기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def binary_search(lst, v):
|
||||
start, end = 0, len(lst)
|
||||
|
||||
while start < end:
|
||||
mid = (start+end) // 2
|
||||
if lst[mid] <= v:
|
||||
end = mid
|
||||
else:
|
||||
start = mid+1
|
||||
|
||||
return start
|
||||
|
||||
def solution():
|
||||
n, new_score, p = map(int, input().rstrip().split())
|
||||
|
||||
if n == 0:
|
||||
print(1)
|
||||
return
|
||||
|
||||
scores = list(map(int, input().rstrip().split()))
|
||||
|
||||
|
||||
if n == p and new_score <= scores[-1]:
|
||||
print(-1)
|
||||
return
|
||||
|
||||
result = binary_search(scores, new_score)
|
||||
|
||||
print(result+1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
|
||||
"""
|
||||
걸린 시간: 1시간 (이분탐색 여러 종류를 공부하면서 하느라 좀 걸렸다..)
|
||||
|
||||
시간 복잡도: O(logn)
|
||||
|
||||
해설: 이분탐색으로 들어갈 곳을 정하고, 이때, 값이 같다면 맨 앞에 놓을 수 있도록 처음으로 lst[mid] > target이 되는 곳을 찾으면 된다.
|
||||
이게 이분탐색 lower_bound이다. 여기서 찾고자 하는 것과 배열 상태에 따라 조건을 잘 설정해야되는데, 우리가 원하는 것은 3번이다.
|
||||
오름차순이라면 x 이상, 초과를 찾을 것이고, 내림차순이라면 x 이하, 미만을 찾는 것이 일반화하는데 편하다.
|
||||
1. 오름차순 배열에서 처음 x 이상을 찾는다면 lst[mid] >= x 이고, mid도 답이 될 수 있고, 왼쪽도 확인해봐야 하기 때문에 r = mid가 된다.
|
||||
2. 오름차순 배열에서 처음 x 초과를 찾는다면 lst[mid] > x 이고, mid가 답이 될 수 있고, 왼쪽도 확인해봐야 하기 때문에 r = mid가 된다.
|
||||
3. 내림차순 배열에서 처음 x 이하를 찾는다면 lst[mid] <= x 이고, mid가 답이 될 수 있고, 왼쪽도 확인해봐야 하기 때문에 r = mid가 된다.
|
||||
4. 내림차순 배열에서 처음 x 미만을 찾는다면 lst[mid] < x 이고, mid가 답이 될 수 있고, 왼쪽도 확인해봐야 하기 때문에 r = mid가 된다.
|
||||
|
||||
아무튼 가장 중요한 것은 현재 mid가 답이 될 수 있는가에 대한 여부와 왼쪽과 오른쪽 중 어디가 답 가능성이 있는 방향인지를 보면
|
||||
1. if 조건과 r, l의 매칭 & 2. r, l에 mid +1을 할지 말지를 정할 수 있다.
|
||||
|
||||
그 외에 이 문제는 경계에 대한 것이었기 때문에 l < r 조건에 [l, r) 구간이었는데,
|
||||
원소를 특정하는 것은 mid를 보고 아니면 버리기 때문에 mid +-1은 항상 해주고, 구간도 [l, r]에 조건도 l <= r이다.
|
||||
"""
|
||||
64
workbook_8708/silver/1244-s4.py
Normal file
64
workbook_8708/silver/1244-s4.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# 스위치 켜고 끄기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def work_mode1(s, s_state, s_num):
|
||||
mul = 1
|
||||
idx = s_num * mul
|
||||
while idx <= s:
|
||||
s_state[idx] = 1 - s_state[idx]
|
||||
mul += 1
|
||||
idx = s_num * mul
|
||||
return
|
||||
|
||||
def work_mode2(s, s_state, s_num):
|
||||
gap = 1
|
||||
s_state[s_num] = 1 - s_state[s_num]
|
||||
while s_num + gap <= s and s_num - gap >= 1:
|
||||
if s_state[s_num + gap] != s_state[s_num - gap]:
|
||||
break
|
||||
s_state[s_num + gap] = 1 - s_state[s_num + gap]
|
||||
s_state[s_num - gap] = 1 - s_state[s_num - gap]
|
||||
gap += 1
|
||||
return
|
||||
|
||||
WORK = {
|
||||
1: work_mode1,
|
||||
2: work_mode2
|
||||
}
|
||||
|
||||
def solution():
|
||||
s = int(input().rstrip())
|
||||
s_state = [-1] + list(map(int, input().rstrip().split()))
|
||||
n = int(input().rstrip())
|
||||
|
||||
for _ in range(n):
|
||||
mode, s_num = map(int, input().rstrip().split())
|
||||
now_work = WORK[mode]
|
||||
now_work(s, s_state, s_num)
|
||||
|
||||
s_state = s_state[1:]
|
||||
|
||||
for i in range(s//20+1):
|
||||
start, end = i*20, (i*20)+20
|
||||
print(*s_state[start:end])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
|
||||
"""
|
||||
걸린 시간: 16분
|
||||
|
||||
시간 복잡도: 남자, 여자 둘 다 한 턴에 스위치 전체 길이인 s에 대해 O(s)이므로 전체 시간 복잡도는 학생 수가 n일 때, O(s*n) 이다.
|
||||
|
||||
해설: 남자(mode1), 여자(mode2)로 작업을 나눠서 배수는 1,2,3 올라가면서 시작 버튼에 곱해주고, 옆으로 확인은 gap을 +1 해주면서
|
||||
확인한다. while 반복문의 기본 규칙은 1과 s 사이의 범위이고, mode2에서 추가 escape는 보고 있는 두 스위치의 상태가 다를 때이다.
|
||||
메인 함수에서는 mode에 맞게 work 함수를 할당 받은 후 작업을 진행하고, 20단위로 끊어서 출력한다.
|
||||
추가로 worker 클래스를 만들어서 상속 받아서 하면 좀 더 안전한 코드가 될 것 같다.
|
||||
|
||||
"""
|
||||
72
workbook_8708/silver/1260-s2.py
Normal file
72
workbook_8708/silver/1260-s2.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# DFS와 BFS
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def dfs(n, g, v):
|
||||
result = []
|
||||
visited = [0]*(n+1)
|
||||
stack = [v]
|
||||
|
||||
while stack:
|
||||
w = stack.pop()
|
||||
if visited[w]:
|
||||
continue
|
||||
|
||||
result.append(w)
|
||||
visited[w] = 1
|
||||
for i in range(len(g[w])-1, -1, -1):
|
||||
stack.append(g[w][i])
|
||||
|
||||
return result
|
||||
|
||||
def bfs(n, g, v):
|
||||
result = []
|
||||
visited = [0]*(n+1)
|
||||
q = deque([v])
|
||||
visited[v] = 1
|
||||
|
||||
while q:
|
||||
w = q.popleft()
|
||||
result.append(w)
|
||||
for k in g[w]:
|
||||
if not visited[k]:
|
||||
q.append(k)
|
||||
visited[k] = 1
|
||||
return result
|
||||
|
||||
def solution():
|
||||
n, m, v = map(int, input().rstrip().split())
|
||||
|
||||
g = [[] for _ in range(n+1)]
|
||||
|
||||
for _ in range(m):
|
||||
v1, v2 = map(int, input().rstrip().split())
|
||||
g[v1].append(v2)
|
||||
g[v2].append(v1)
|
||||
|
||||
for i in range(1, n+1):
|
||||
g[i].sort()
|
||||
|
||||
print(*dfs(n, g, v))
|
||||
print(*bfs(n, g, v))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 34분
|
||||
|
||||
시간 복잡도: 간선 수에 따라 for문을 돌아보는 차이가 난다. 또한 어디 노드에 연결이 얼마나 되어 있느냐에 따라 sort의 차이도 난다.
|
||||
|
||||
해설: dfs는 시작 노드를 stack에 넣고 pop해가면서 인접 노드를 넣는 방식으로 구현이 가능하다.
|
||||
이때, visited를 pop하고 찍음으로써 이전에 인접한 노드로 나왔더라도 한 번 더 나왔을 때 다시 넣을 수 있게 한다.
|
||||
이는 깊이 탐색을 위해 뒤에서 나올수록 우선순위가 높아짐을 의미한다.
|
||||
bfs는 시작 노드를 queue에 넣고 popleft 해가면서 인접 노드를 넣는 방식으로 구현이 가능하다.
|
||||
이때, visited를 queue에 append 하면서 찍음으로써 이후에 인접한 노드로 또 나왔을 경우 다시 못 들어가게 한다.
|
||||
이는 너비 탐색을 위해 먼저 나왔을수록 우선순위가 높음을 의미한다.
|
||||
"""
|
||||
61
workbook_8708/silver/1283-s1.py
Normal file
61
workbook_8708/silver/1283-s1.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# 단축키 지정
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def check_word_first(words, shortcut):
|
||||
for i in range(len(words)):
|
||||
c = words[i][0].upper()
|
||||
if not shortcut.get(c, 0):
|
||||
shortcut[c] = 1
|
||||
return i
|
||||
return -1
|
||||
|
||||
def check_word(word, shortcut):
|
||||
for i in range(len(word)):
|
||||
c = word[i].upper()
|
||||
if not shortcut.get(c, 0):
|
||||
shortcut[c] = 1
|
||||
return i
|
||||
return -1
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
shortcut = {}
|
||||
|
||||
for _ in range(n):
|
||||
option = input().rstrip().split()
|
||||
shortcut_idx = check_word_first(option, shortcut)
|
||||
|
||||
if shortcut_idx != -1:
|
||||
option[shortcut_idx] = f"[{option[shortcut_idx][0]}]" + option[shortcut_idx][1:]
|
||||
print(*option)
|
||||
continue
|
||||
|
||||
idx = 0
|
||||
while idx < len(option):
|
||||
shortcut_idx = check_word(option[idx], shortcut)
|
||||
if shortcut_idx != -1:
|
||||
option[idx] = option[idx][:shortcut_idx] + f"[{option[idx][shortcut_idx]}]" + option[idx][shortcut_idx+1:]
|
||||
break
|
||||
idx += 1
|
||||
|
||||
print(*option)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 41분
|
||||
|
||||
시간 복잡도: 완전 탐색이기 때문에 O(5*10*n)이다.
|
||||
|
||||
해설: 30개의 옵션에 1개 옵션 당 5개 이하 단어와 1개의 단어에 10개 이하의 알파벳이면 다 돌아봤자 1500이다.
|
||||
따라서 조건대로 구현하면 된다. 대소문자를 구분하지 않기 때문에 다 upper로 만들어서 현재 사용된 옵션을 기록한다.
|
||||
단어 첫 글자들을 보며 옵션 설정하고, 한 단어씩 쭉 보면서 옵션 설정을 한다.
|
||||
옵션을 설정하면 출력 형태를 맞춰서 리스트에 저장하고 마지막에 한번에 출력한다.
|
||||
"""
|
||||
35
workbook_8708/silver/13305-s3.py
Normal file
35
workbook_8708/silver/13305-s3.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# 주유소
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
dist = list(map(int, input().rstrip().split()))
|
||||
price = list(map(int, input().rstrip().split()))
|
||||
|
||||
least_price = float('inf')
|
||||
|
||||
result = 0
|
||||
for i in range(n-1):
|
||||
if price[i] < least_price:
|
||||
least_price = price[i]
|
||||
result += (dist[i]*least_price)
|
||||
|
||||
|
||||
print(result)
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
|
||||
|
||||
"""
|
||||
걸린 시간: 12분
|
||||
|
||||
시간 복잡도: dist 길이만큼 한 번 돌기 때문에 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 현재 지역 다음에 본인보다 더 싼게 있으면 거기까지만 가고 그 다음부터는 싼 곳에서 기름을 사야한다.
|
||||
가장 쌌던 가격을 계속 기록해가면서 price를 마지막-1 까지 순회하면 끝.
|
||||
"""
|
||||
77
workbook_8708/silver/1406-s2.py
Normal file
77
workbook_8708/silver/1406-s2.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# 에디터
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def l(left_q, right_q):
|
||||
if len(left_q) >= 1:
|
||||
right_q.appendleft(left_q.pop())
|
||||
return
|
||||
|
||||
def d(left_q, right_q):
|
||||
if len(right_q) >= 1:
|
||||
left_q.append(right_q.popleft())
|
||||
return
|
||||
|
||||
def b(left_q):
|
||||
if len(left_q) >= 1:
|
||||
left_q.pop()
|
||||
return
|
||||
|
||||
def p(left_q, w):
|
||||
left_q.append(w)
|
||||
return
|
||||
|
||||
COMMANDS = {
|
||||
"L": l,
|
||||
"D": d,
|
||||
"B": b,
|
||||
"P": p,
|
||||
}
|
||||
|
||||
def excute(left_q, right_q, *c):
|
||||
command = COMMANDS.get(c[0], None)
|
||||
if c[0] == "P":
|
||||
command(left_q, c[1])
|
||||
elif c[0] == "L" or c[0] == "D":
|
||||
command(left_q, right_q)
|
||||
elif c[0] == "B":
|
||||
command(left_q)
|
||||
else:
|
||||
return
|
||||
return
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
m = int(input().rstrip())
|
||||
|
||||
left_q = deque(list(s))
|
||||
right_q = deque([])
|
||||
|
||||
for _ in range(m):
|
||||
excute(left_q, right_q, *(input().rstrip().split()))
|
||||
|
||||
result = list(left_q) + list(right_q)
|
||||
print("".join(result))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 30분
|
||||
|
||||
시간 복잡도: deque는 pop이나 append가 어디든 O(1)이므로 명령어 수행은 항상 O(1)이고, m번 명령을 반복하기 때문에 O(m)이다.
|
||||
그 후 마지막에 두 deque를 합쳐서 출력하기 때문에 n개의 단어에서 m만큼 글자가 추가 되었다면 O(n+m)이다.
|
||||
따라서 전체 시간복잡도는 O(n+m)이다.
|
||||
|
||||
해설: 커서를 기준으로 양쪽에 deque를 배치한 후 l, d로 커서를 움직이면 양쪽 deque에서 요소들을 옮기고, b, p로 요소를 지우거나 추가하면
|
||||
커서 기준 왼쪽으로 동작한다고 했으므로 왼쪽 deque로 요소를 조정한다. 마지막에 두 deque를 list로 만들어서 합치고 출력하면 끝
|
||||
|
||||
확장성을 위해 dispatch 전략을 사용했지만 l,d,b,p의 인자가 달라서 excute 함수에서 또 분기를 했다. -> l,d,b,p의 인자를 같게 하면 됨
|
||||
자료구조가 deque에서 다른 것으로 바뀐다면 다 수정해야 하기 때문에 결합도가 너무 높다.
|
||||
-> 추상화 계층 하나를 추가해서 Editor라는 클래스를 만들고 거기다가 기능들 쓴 다음에 l,d,b,p가 그걸 받아오면 나중에 Editor 클래스만 바꾸면 됨
|
||||
"""
|
||||
40
workbook_8708/silver/1446-s1.py
Normal file
40
workbook_8708/silver/1446-s1.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# 지름길
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, d = map(int, input().rstrip().split())
|
||||
shortcut = {}
|
||||
for _ in range(n):
|
||||
start, end, cost = map(int, input().rstrip().split())
|
||||
if end > d:
|
||||
continue
|
||||
if not shortcut.get(end, []):
|
||||
shortcut[end] = []
|
||||
shortcut[end].append((start, cost))
|
||||
|
||||
dp = [0] * (d+1)
|
||||
|
||||
for i in range(1, d+1):
|
||||
shortcut_list = shortcut.get(i, [])
|
||||
dp[i] = min(min([dp[s]+c for s, c in shortcut_list]) if shortcut_list else float('inf'), dp[i-1]+1)
|
||||
|
||||
print(dp[d])
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 30분
|
||||
|
||||
시간 복잡도: 모든 지점에 대해 dp 값을 구하는데, 이때 한 지점은 연결된 지름길만큼 반복한다.
|
||||
하지만 지름길 하나 당 한번만 보기 때문에 전체 시간복잡도는 O(n+d)이다.
|
||||
|
||||
해설: 지름길의 도착 위치 기준으로 그냥 가는 것과 여러 지름길 중 하나를 선택하는 것과 같이
|
||||
여러 개를 비교해야했다. 그리고 비교를 하는 것이 과거의 지점에서 계산을 하는 것이기 때문에 dp를 생각했다.
|
||||
현재 지점의 dp를 계산할 때 이 곳에 올 수 있는 모든 경우의 수 중 cost가 최소인 것을 구하면 된다.
|
||||
따라서 지름길을 통해 오는 것과 바로 한 칸 전 위치에서 +1로 오는 경우 중 구하면 된다.
|
||||
"""
|
||||
74
workbook_8708/silver/14940-s1.py
Normal file
74
workbook_8708/silver/14940-s1.py
Normal file
@@ -0,0 +1,74 @@
|
||||
# 쉬운 최단거리
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def find_target(grid, n, m):
|
||||
for i in range(n):
|
||||
for j in range(m):
|
||||
if grid[i][j] == 2:
|
||||
target = (i, j)
|
||||
return target
|
||||
return (-1, -1)
|
||||
|
||||
def set_zero_land(grid, visited, n, m):
|
||||
for i in range(n):
|
||||
for j in range(m):
|
||||
if grid[i][j] == 0:
|
||||
visited[i][j] = 0
|
||||
return
|
||||
|
||||
|
||||
def bfs(grid, target, n, m):
|
||||
dr = [1, -1, 0, 0]
|
||||
dc = [0, 0, 1, -1]
|
||||
visited = [[-1]*m for _ in range(n)]
|
||||
set_zero_land(grid, visited, n, m)
|
||||
q = deque([target])
|
||||
visited[target[0]][target[1]] = 0
|
||||
|
||||
while q:
|
||||
r, c = q.popleft()
|
||||
for i in range(4):
|
||||
now_r, now_c = r+dr[i], c+dc[i]
|
||||
if now_r == target[0] and now_c == target[1]:
|
||||
continue
|
||||
if 0 <= now_r < n and 0 <= now_c < m and grid[now_r][now_c] != 0 and visited[now_r][now_c] == -1:
|
||||
q.append((now_r, now_c))
|
||||
visited[now_r][now_c] = visited[r][c] + 1
|
||||
|
||||
return visited
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
|
||||
grid = [list(map(int, input().rstrip().split())) for _ in range(n)]
|
||||
|
||||
target = find_target(grid, n, m)
|
||||
|
||||
result = bfs(grid, target, n, m)
|
||||
|
||||
for i in range(n):
|
||||
print(*result[i])
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 55분
|
||||
|
||||
시간 복잡도: target 찾고, 0 세팅 하는데 O(nm)이고,
|
||||
bfs는 한 노드마다 4번의 인접 노드를 확인하므로 O(4nm)
|
||||
전체 시간복잡도는 O(nm)이다.
|
||||
|
||||
해설: 각 점에서 도착지까지 계속 찾아가는건 말이 안되고, 인접 점의 결과에 +1을 하는 식으로
|
||||
O(1)에 찾도록 생각을 하였다. dp가 떠올랐지만,
|
||||
target 지점을 기준으로 +1씩 해야하기 때문에 target이 중간 어딘가에 있으면 dp 테이블을 채우기 애매했다.
|
||||
따라서 너비우선 탐색을 떠올렸고, bfs로 진행했다.
|
||||
조건들이 조금 귀찮아서 몇 번 틀렸는데, 0인 땅은 그냥 0이고, 1인데 못 가는 땅은 -1로 출력을 해야했다.
|
||||
따라서 bfs 세팅에서 기본 visited를 -1로 잡고, 0인 땅은 0으로 초기화 해주는 작업을 했다.
|
||||
"""
|
||||
69
workbook_8708/silver/1515-s2.py
Normal file
69
workbook_8708/silver/1515-s2.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# 수 이어 쓰기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def check_parttern(now, target):
|
||||
idx = 0
|
||||
len_target = len(target)
|
||||
for c1 in now:
|
||||
while idx < len_target:
|
||||
if c1 == target[idx]:
|
||||
idx += 1
|
||||
break
|
||||
else:
|
||||
idx += 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
len_s = len(s)
|
||||
i = 0
|
||||
target = 0
|
||||
while i < len_s:
|
||||
target += 1
|
||||
j = i
|
||||
while j < len_s and int(s[i:j+1]) <= target:
|
||||
now = s[i:j+1]
|
||||
if check_parttern(now, str(target)):
|
||||
j += 1
|
||||
else:
|
||||
break
|
||||
i = j
|
||||
print(target)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 53분
|
||||
|
||||
시간 복잡도: s의 길이가 3000까지가 최대라고 했기 때문에 최악의 경우 0이 3000개 있으면
|
||||
target이 30000까지 간다. 즉, len(s) = n, max(target) = 10n = T이다.
|
||||
근데 s의 한 숫자는 한번씩만 보는데 내 코드는 한번 볼때 다음것이 패턴이
|
||||
가능하다면 중복해서 보기 때문에 O(j^2)이긴 하지만 이렇게 한번하면 그만큼 가장 최근의 것은 1번 본다.
|
||||
따라서 전체 시간복잡도는 O((n+T)^2) 정도이다.
|
||||
근데 s의 i번째 수를 보는 것의 중복을 없애면 O(TlogT)가 될 수 있을 것 같다.(log 밑은 10)
|
||||
|
||||
|
||||
|
||||
해설: 처음엔 문제 이해가 좀 어려웠는데 써가면서 하니까 이해가 됐다.
|
||||
그리고 주어진 테스트 케이스가 엄청 복잡한 것을 보면 규칙 찾아서 하는 것이라는 걸 의심해보자.
|
||||
1~10까지를 한 세트라고 했을 때 지금 보는 숫자보다 작거나 같은 숫자가 나오면 한 세트가 넘어간 것이다.
|
||||
이걸로 규칙 세워서 가려고 했는데 다음 세트로 넘어갈수록 숫자가 10의 자리나 100의 자리가 생기고, 바뀌고
|
||||
그러기 때문에 쉽지 않았다. -> 주어진 숫자를 쭉 보면서 답이 될 수 있는 숫자를 하나씩 키워나가자.
|
||||
s의 숫자들을 하나씩 보면서 target이 될 수 있는 숫자라면, 즉 target의 substring이라면 s의 다음 숫자를 보고
|
||||
target도 하나 키우는 방식으로 진행했다. 아니라면 당연히 target만 하나 키우기.
|
||||
여기서 substring 구하는 방식을 s의 i번째를 확인했음에도 안쪽 while문으로 i~i+j번째까지 계속 중복 확인을 했다.
|
||||
이 부분을 따로 함수로 빼서 고치든가 했어야 했다.(어차피 그래도 답은 틀림)
|
||||
아무튼 나는 now in target 방법으로 진행했는데, 반례가 존재했다. s의 11이 target의 101을 대표하지 못했다.
|
||||
in으로는 0이 있어서 안되기 때문이다.
|
||||
따라서 target의 한 글자와 s의 한글자씩 보는 방식으로 진행했다.
|
||||
역시 i~i+j번째를 보기까지 중복이 있긴 해서 이 부분을 고쳐야 하긴 하지만 아무튼 통과했다.
|
||||
"""
|
||||
32
workbook_8708/silver/1522-s1.py
Normal file
32
workbook_8708/silver/1522-s1.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# 문자열 교환
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
|
||||
k = s.count("a")
|
||||
k_count = {"a": s[:k].count("a"), "b": s[:k].count("b")}
|
||||
circle = s + s
|
||||
result = k_count["b"]
|
||||
for i in range(1, len(circle)-k):
|
||||
k_count[circle[i-1]] -= 1
|
||||
k_count[circle[i+k-1]] += 1
|
||||
result = min(result, k_count["b"])
|
||||
|
||||
print(result)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 못 품
|
||||
|
||||
시간 복잡도: 전체에서 a의 개수(k)를 세고, k구간씩 옮겨가며 b개수를 슬라이딩 윈도우로 업데이트하기 때문에 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 원형이라고 했기 때문에 같은 것 2배를 해준 문자열을 만든다. 여기서 기존 a가 다 연속이면 되기 때문에
|
||||
a의 개수 k를 구해서 원형에서 k구간씩 확인하며 b를 다 빼주면 되는데, 이때 b개수의 최소값이 답이다.
|
||||
"""
|
||||
44
workbook_8708/silver/1697-s1.py
Normal file
44
workbook_8708/silver/1697-s1.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# 숨바꼭질
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
|
||||
max_len = 100000
|
||||
line = [0 for _ in range(max_len+1)]
|
||||
move = [-1, 1]
|
||||
|
||||
q = deque([n])
|
||||
line[n] = 1
|
||||
|
||||
while q:
|
||||
now = q.popleft()
|
||||
for m in move:
|
||||
now_move = now + m
|
||||
if 0 <= now_move < max_len+1 and line[now_move] == 0:
|
||||
q.append(now_move)
|
||||
line[now_move] = line[now] + 1
|
||||
if 0 <= now*2 < max_len+1 and line[now*2] == 0:
|
||||
q.append(now*2)
|
||||
line[now*2] = line[now] + 1
|
||||
|
||||
print(line[k]-1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 몰라
|
||||
|
||||
시간 복잡도: 한 지점 당 큐에 한 번씩만 들어갔다가 나오기 때문에 전체 지점만큼의 시간이 걸린다. 따라서 O(100000)이다.
|
||||
|
||||
해설: 특정 위치를 볼 때 그 위치로부터 //2, -1, +1 지점에서 +1 한 것들과 기존 지점까지 총 4개 값의 최소값을 가져오면서 dp 테이블을
|
||||
갱신하면 될 것 같았는데, 이렇게 되면 dp 테이블을 채우는 방향에 따라 비교해야하는 4지점이 다 안 채워진 경우가 있다.
|
||||
따라서 bfs로 한번 이동하는 것을 하나의 계층으로 생각해서 진행하면 된다.
|
||||
"""
|
||||
36
workbook_8708/silver/17266-s4.py
Normal file
36
workbook_8708/silver/17266-s4.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# 어두운 굴다리
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
m = int(input().rstrip())
|
||||
x = list(map(int, input().rstrip().split()))
|
||||
result = 0
|
||||
for i in range(1, m):
|
||||
now = (x[i]-x[i-1])//2 if (x[i]-x[i-1])%2==0 else (x[i]-x[i-1])//2 + 1
|
||||
result = max(result, now)
|
||||
|
||||
result = max(result, x[0]-0, n-x[-1])
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 26분
|
||||
|
||||
시간 복잡도: 0에서 첫 번째 위치를 빼는 것이랑, 끝에서 마지막 위치를 빼는 것을 포함하여 약 m번의 연산을 진행한다.
|
||||
m이 n보다 작으므로 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 가로등이 놓일 위치 사이의 거리가 가장 큰 값을 2로 나눈 값이 답이다. 반씩 나눠서 그 구간을 커버해야하기 때문이다.
|
||||
x를 순차적으로 가면서 앞의 위치와 차이//2 중 최대를 찾으면 되는데, 이때, 차이가 홀수인 경우 +1을 해줘야 커버가된다.
|
||||
삼항연산자로 구분했지만 ceil을 하거나 -(-n//2)를 하면 같은 효과를 볼 수 있다.
|
||||
파이썬의 //는 무조건 음의 무한대로 내림하기 때문에 -5 // 2는 -2.5가 -3이 된다. => 올림 효과를 볼 수 있다.
|
||||
마지막으로 0과 n에는 가로등 하나가 온전히 감당해야 하므로 마지막에 비교해주면 끝.
|
||||
"""
|
||||
99
workbook_8708/silver/17484-s3.py
Normal file
99
workbook_8708/silver/17484-s3.py
Normal file
@@ -0,0 +1,99 @@
|
||||
# 진우의 달 여행
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
|
||||
direction = [-1, 0, 1]
|
||||
|
||||
grid = [list(map(int, input().rstrip().split())) for _ in range(n)]
|
||||
|
||||
dp = [[[0]*3 for _ in range(m)] for _ in range(n)]
|
||||
|
||||
for i in range(m):
|
||||
for j in range(len(direction)):
|
||||
dp[0][i][j] = grid[0][i]
|
||||
|
||||
for i in range(1, n):
|
||||
for j in range(m):
|
||||
for k in range(len(direction)):
|
||||
if j == 0:
|
||||
dp[i][j][k] = min([dp[i-1][j+direction[h]][h] for h in range(len(direction)) if h != k and direction[h] != -1]) + grid[i][j]
|
||||
elif j == m-1:
|
||||
dp[i][j][k] = min([dp[i-1][j+direction[h]][h] for h in range(len(direction)) if h != k and direction[h] != 1]) + grid[i][j]
|
||||
else:
|
||||
dp[i][j][k] = min([dp[i-1][j+direction[h]][h] for h in range(len(direction)) if h != k]) + grid[i][j]
|
||||
|
||||
print(min([min(dp[n-1][j]) for j in range(m)]))
|
||||
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
|
||||
"""
|
||||
풀이(2) -> dp
|
||||
|
||||
걸린 시간: 45분
|
||||
|
||||
시간 복잡도: n*m*3(방향)으로 된 3차원 dp를 채우는데, 방향을 채울 때 본인을 제외한 방향들의 최소를 구하기 때문에 *2를 해서 (n*m*3*2)이다.
|
||||
|
||||
|
||||
해설: 다른 풀이에서 DP가 있다는 것을 알게되어서 두 번째 풀이를 진행했다.
|
||||
i, j, k는 행, 열, 이전 방향이라고 할때, dp[i][j][k]를 구하면 i-1번째 행에서 direction[k]방향을 제외한 j열의 값들 중에 최소와
|
||||
현재 행렬 값(grid[i][j])의 합이다.
|
||||
즉 [i][j][0]은 direction[0]이 -1방향이므로 [i-1][j-1]에서 값을 가져오는데 [i-1][j-1][0]을 제외한 값들 중에 최소를 가져온다.
|
||||
"""
|
||||
|
||||
"""
|
||||
풀이(1) -> dfs
|
||||
|
||||
걸린 시간: 35분
|
||||
|
||||
시간 복잡도: 첫 행에서 갈 수 있는 경우의 수는 3이고 마지막 행을 제외한 행에서 경우의 수는 2이므로 3*2^(n-2) 이다.
|
||||
이것을 열 개수만큼 반복해야 하므로 3*2^(n-2)*m 이다. 사실상 O(2^n * m)이라서 말이 안되는 시간복잡도이지만 조건때문에 그냥 했다.
|
||||
|
||||
해설: 2 <= n, m <= 6인걸 봐서는 모든 경우의 수를 확인해보라는 것 같다. (3 * 2^4) * 6 개이므로 얼마 안된다.
|
||||
dfs의 기저를 depth가 n-1보다 클때, 즉 마지막 행에 도달했을 때로 잡았고, 지금까지 더해온 total에 마지막 grid 값을 더한 뒤
|
||||
result 리스트에 넣고 마지막에 min을 구해서 출력하도록 하였다.
|
||||
이전에 어디로 갔는지도 계속 가져가며 갈 수 있는 전체 방향에서 이전에 간 방향 빼고, 열 밖으로 나가는 것까지 빼면 된다.
|
||||
total을 어떻게 계속 갱신할지 dfs에 선언하면 꼬일 것 같아서 고민했는데 그냥 인자로만 계속 넘기면 괜찮은 것 같다.
|
||||
|
||||
"""
|
||||
|
||||
# result = []
|
||||
|
||||
# def solution():
|
||||
# n, m = map(int, input().rstrip().split())
|
||||
|
||||
# grid = [list(map(int, input().rstrip().split())) for _ in range(n)]
|
||||
|
||||
# dx = [-1, 0, 1]
|
||||
# dy = [1, 1, 1]
|
||||
|
||||
# def dfs(depth, col, before, total):
|
||||
# if depth >= n-1:
|
||||
# total += grid[depth][col]
|
||||
# result.append(total)
|
||||
# return
|
||||
|
||||
# for i in range(3):
|
||||
# if i == before or col+dx[i] >= m or col+dx[i] < 0:
|
||||
# continue
|
||||
# dfs(depth+dy[i], col+dx[i], i, total+grid[depth][col])
|
||||
|
||||
|
||||
# return total
|
||||
|
||||
# for i in range(m):
|
||||
# dfs(0, i, -1, 0)
|
||||
|
||||
|
||||
# print(min(result))
|
||||
# return
|
||||
|
||||
|
||||
# solution()
|
||||
51
workbook_8708/silver/17615-s1.py
Normal file
51
workbook_8708/silver/17615-s1.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# 볼 모으기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def count_result(n, balls, left, right, ball_count):
|
||||
left_count, right_count = 0, 0
|
||||
left_idx, right_idx = 0, n-1
|
||||
while left_idx <= n-1 and balls[left_idx] == left:
|
||||
left_count += 1
|
||||
left_idx += 1
|
||||
|
||||
while right_idx >= 0 and balls[right_idx] == right:
|
||||
right_count += 1
|
||||
right_idx -= 1
|
||||
|
||||
return min(ball_count[left]-left_count, ball_count[right]-right_count)
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
balls = list(input().rstrip())
|
||||
|
||||
ball_count = {"R": 0, "B": 0}
|
||||
|
||||
for b in balls:
|
||||
ball_count[b] += 1
|
||||
|
||||
result = min(count_result(n, balls, "R", "B", ball_count), count_result(n, balls, "B", "R", ball_count))
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분
|
||||
|
||||
시간 복잡도: count_result가 왼쪽, 오른쪽에 대해 첫 묶음이 몇 개인지 계산하는데 최악의 경우 전체이므로,
|
||||
O(n)이다. 처음에 ball_count를 셀 때 O(n)이고, count_result가 2번이므로 O(3n), 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 같은 것끼리 묶인 최종 상태는 한쪽 끝이 B, R 하나씩 있어야 된다.
|
||||
따라서 큰 경우의 수는 양 끝이 R, B 이거나 B, R인 경우이다.
|
||||
이제 각 경우의 수마다 R을 넘길지 B를 넘길지 계산하면 되는데,
|
||||
정해진 경우의 끝에 따라서 같은 묶음만 뺀 개수를 세면 된다.
|
||||
경우의 수 1) R, B일때 왼쪽 R 묶음 제거한 R 개수, 오른쪽 B 묶음 제거한 B개수 중 최소
|
||||
경우의 수 2) B, R일때 왼쪽 B 묶음 제거한 B 개수, 오른쪽 R 묶음 제거한 R개수 중 최소
|
||||
두 경우의 수 중 최소 값 구하면 된다.
|
||||
"""
|
||||
35
workbook_8708/silver/1927-s2.py
Normal file
35
workbook_8708/silver/1927-s2.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# 최소 힙
|
||||
|
||||
import sys
|
||||
import heapq
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
h = []
|
||||
|
||||
for i in range(n):
|
||||
v = int(input().rstrip())
|
||||
if v == 0:
|
||||
if len(h) == 0:
|
||||
print(0)
|
||||
continue
|
||||
print(heapq.heappop(h))
|
||||
else:
|
||||
heapq.heappush(h, v)
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 5분
|
||||
|
||||
시간 복잡도: heappush와 heappop 모두 현재 트리의 높이 즉, logn만큼 든다.
|
||||
트리 길이가 점점 길어져서 n까지 가는 것이기 때문에 평균적으로 O(logn)이다.
|
||||
n번 진행하기 때문에 전체 시간복잡도는 O(nlogn)이다.
|
||||
|
||||
해설: 대놓고 힙 써서 구현하라고 해서 쉬웠다.
|
||||
0일때 pop하는데, 배열 길이가 0이면 0 출력하도록 설정
|
||||
넣을때는 heappush, 뺄때는 heappop 하면 끝
|
||||
"""
|
||||
58
workbook_8708/silver/19637-s3.py
Normal file
58
workbook_8708/silver/19637-s3.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# IF문 좀 대신 써줘
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def binary_search(target, badge):
|
||||
l, r = 0, len(badge)
|
||||
|
||||
while l < r:
|
||||
mid = (l+r)//2
|
||||
if badge[mid][1] >= target:
|
||||
r = mid
|
||||
else:
|
||||
l = mid + 1
|
||||
return l
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
|
||||
badge = []
|
||||
name, value = input().rstrip().split()
|
||||
badge.append((name, int(value)))
|
||||
for i in range(n-1):
|
||||
name, value = input().rstrip().split()
|
||||
if badge[-1][1] == int(value):
|
||||
continue
|
||||
badge.append((name, int(value)))
|
||||
|
||||
for i in range(m):
|
||||
target = int(input().rstrip())
|
||||
idx = binary_search(target, badge)
|
||||
print(badge[idx][0])
|
||||
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: m개의 값에 대해 n범위에서 이분탐색을 진행하기 때문에 O(mlogn)
|
||||
|
||||
해설: 문제가 너무 단순해서 뭔가 했는데 n, m <= 10^5 이기 때문에 n에서 비교를 최대한 줄이는 것이 핵심이다.
|
||||
n으로 만들어진 수직선 상에 m이 들어갈 위치를 찾으면 되기 때문에 이분탐색으로 진행한다.
|
||||
10^5는 17정도에서 끝낼 수 있다. badge에 상한 값이 겹치는 애들은 첫번째만 넣고, m개 받으면서 이분탐색 진행
|
||||
|
||||
이분탐색 정리했는데 자꾸 헷갈리니까 다시 정리
|
||||
내가 찾고자 하는건 badge의 idx이다. 즉 mid 기준으로 생각하는게 편하다.
|
||||
지금 문제는 target이 어느 상한에 속하나인데, 100이라면 100이상의 상한을 찾아서 가장 먼저 나오는
|
||||
상한값이 답인 것이다. 따라서 badge[mid][1] >= target으로 기본을 잡으면 되고,
|
||||
저게 성립하면 mid는 답이 될 수 있지만 왼쪽에 답이 있을 수도 있다.
|
||||
따라서 r을 움직여야하고, 현재 mid를 포함한 값이 되야 한다. r = mid
|
||||
반대 상황은 badge가 target보다 작은거니까 현재 mid가 답이 될 수 없으므로 l = mid + 1
|
||||
원소의 유무 판단이 아닌 들어갈 곳 찾기기 때문에 l, r = 0, len(badge)로 한다.
|
||||
while문 기본 조건은 들어갈 자리를 찾는 것이기 때문에 l = r일때는 알아보는 것이 의미 없다. 따라서 while l < r
|
||||
끝.
|
||||
"""
|
||||
78
workbook_8708/silver/19941-s3.py
Normal file
78
workbook_8708/silver/19941-s3.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# 햄버거 분배
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def clear_left(d, i, k):
|
||||
while len(d) >= 1 and d[0][0] < i - (k):
|
||||
d.popleft()
|
||||
return
|
||||
|
||||
def clear_right(d, i, k):
|
||||
while len(d) >= 1 and d[-1][0] < i - (k):
|
||||
d.pop()
|
||||
return
|
||||
|
||||
def manage_h(d, i, t, result):
|
||||
if len(d) >= 1 and d[-1][1] == "P":
|
||||
d.pop()
|
||||
result += 1
|
||||
else:
|
||||
d.append((i, t))
|
||||
return result
|
||||
|
||||
def manage_p(d, i, t, result):
|
||||
if len(d) >= 1 and d[0][1] == "H":
|
||||
d.popleft()
|
||||
result += 1
|
||||
else:
|
||||
d.appendleft((i, t))
|
||||
return result
|
||||
|
||||
MANAGEMENT = {
|
||||
"H": manage_h,
|
||||
"P": manage_p
|
||||
}
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
|
||||
table = input().rstrip()
|
||||
|
||||
d = deque()
|
||||
|
||||
result = 0
|
||||
for i, t in enumerate(table):
|
||||
clear_left(d, i, k)
|
||||
clear_right(d, i, k)
|
||||
manager = MANAGEMENT.get(t, None)
|
||||
|
||||
if not manager:
|
||||
return -1
|
||||
|
||||
result = manager(d, i, t, result)
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 35분
|
||||
|
||||
시간 복잡도: deque의 길이를 k로 유지하면서 테이블에 있는 하나의 요소는 deque에 1번만 들어오거나 나가기 때문에
|
||||
한 요소 당 시간 복잡도는 O(1)이고 전체 요소에 대해서 진행하기 때문에 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: P, H가 짝을 지어서 사라지면 된다고 생각하여 스택을 떠올렸고, 오래된 H나 P는 선택할 수 없게 지워버리는 방법을 생각했을 때
|
||||
큐가 생각나서, 합쳐서 deque를 사용하기로 하였다.
|
||||
처음에는 오래된 것들을 나가는 방향을 popleft, P/H가 들어오는 곳은 append, 짝을 이뤄서 나가는 방향을 pop으로 생각했는데,
|
||||
이러면 과거 H를 P가 먹을 수 있는 상황에서 가장 최신 H만 먹기 때문에 최선이 아니다.
|
||||
따라서 P는 들어오는 것과 짝 맞춰서 나가는 것을 왼쪽, H는 오른쪽으로 함으로써 우선순위를 오래 기다린 사람과 오래된 햄버거로 하였다.
|
||||
그리고 이번에 들어오는 요소는 k 범위 이전 것들과는 전혀 상호작용할 수 없으므로 매번 clear를 왼쪽, 오른쪽을 다 해준다.
|
||||
|
||||
참고: len(list, deque, set, dict)들 모두 원소의 개수를 따로 저장하고 있기 때문에 O(1)이다.
|
||||
"""
|
||||
47
workbook_8708/silver/20006-s2.py
Normal file
47
workbook_8708/silver/20006-s2.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# 랭킹전 대기열
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
p, m = map(int, input().rstrip().split())
|
||||
|
||||
room = {}
|
||||
for i in range(p):
|
||||
l, n = input().rstrip().split()
|
||||
l = int(l)
|
||||
for j in room:
|
||||
if len(room[j]) < m and l >= j[0]-10 and l <= j[0]+10:
|
||||
room[j].append((l, n))
|
||||
break
|
||||
else:
|
||||
room[(l, n)] = [(l, n)]
|
||||
|
||||
for v in room.values():
|
||||
if len(v) == m:
|
||||
print("Started!")
|
||||
else:
|
||||
print("Waiting!")
|
||||
for j in sorted(v, key=lambda x: x[1]):
|
||||
print(*j)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분
|
||||
|
||||
시간 복잡도: p개의 플레이어를 방에 분배하기 위해 각 방을 확인해보는 시간 복잡도도 균등분배 기준으로 p//m개 방이므로, O(p* p//m) = O(p^2*m)이다.
|
||||
room.values()를 확인하며 정렬하고 출력하는 것은 p//m 즉 균등분배 가정으로 나올 수 있는 최대 방 개수만큼 정렬하기 때문에
|
||||
O(mlogm * p//m)이므로 O(plogm)이다.
|
||||
따라서 전체 시간 복잡도는 O(p^2*m)이다.
|
||||
p, m <= 300이기 때문에 그냥했지만 크기가 커진다면 모르기 때문에 들어갈 방을 범위로 나타내서 이분탐색을 하면 줄일 수 있다.
|
||||
물론 방이 다 차면 같은 범위를 가지는 방이 또 필요할 수 있기 때문에 적절히 조치를 취해야한다.
|
||||
|
||||
해설: p개의 플레이어를 확인하면서 맞는 room이 있다면 넣고, 없다면 room을 만든다. 이때, 딕셔너리를 사용했는데 level만 키로 쓰면 중복될 수 있으므로,
|
||||
(level, name)을 키로 써서 해야한다. 플레이어마다 생성된 room을 순서대로 다 범위를 확인한다. (이분 탐색을 쓰면 더 좋겠다.)
|
||||
다 room에 넣은 후 room 길이에 따라 started와 waiting을 쓰고, 이름 순으로 정렬한 뒤 출력한다.
|
||||
"""
|
||||
72
workbook_8708/silver/20125-s4.py
Normal file
72
workbook_8708/silver/20125-s4.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# 쿠키의 신체 측정
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def find_heart(grid, n, k):
|
||||
for i in range(n):
|
||||
if grid[k][i] == "*":
|
||||
return [k+1, i]
|
||||
else:
|
||||
return [-1, -1]
|
||||
|
||||
def down_check_star(grid, n, x, y):
|
||||
length = 0
|
||||
while x <= n-1:
|
||||
if grid[x][y] != "*":
|
||||
break
|
||||
length += 1
|
||||
x += 1
|
||||
return length
|
||||
|
||||
def row_check_star(grid, n, x, y, dir): # 오른쪽 +1, 왼쪽 -1
|
||||
length = 0
|
||||
while y <= n-1 and y >= 0:
|
||||
if grid[x][y] != "*":
|
||||
break
|
||||
length += 1
|
||||
y += dir
|
||||
return length
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
grid = []
|
||||
heart = [-1, -1]
|
||||
left_arm = 0
|
||||
right_arm = 0
|
||||
mid = 0
|
||||
left_leg = 0
|
||||
right_leg = 0
|
||||
for i in range(n):
|
||||
grid.append(input().rstrip())
|
||||
if heart[0] == -1:
|
||||
heart = find_heart(grid, n, i)
|
||||
|
||||
left_arm = row_check_star(grid, n, heart[0], heart[1]-1, -1)
|
||||
right_arm = row_check_star(grid, n, heart[0], heart[1]+1, +1)
|
||||
mid = down_check_star(grid, n, heart[0]+1, heart[1])
|
||||
left_leg = down_check_star(grid, n, heart[0]+mid+1, heart[1]-1)
|
||||
right_leg = down_check_star(grid, n, heart[0]+mid+1, heart[1]+1)
|
||||
|
||||
heart[0] += 1
|
||||
heart[1] += 1
|
||||
print(*heart)
|
||||
print(left_arm, right_arm, mid, left_leg, right_leg)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 30분
|
||||
|
||||
시간 복잡도: 팔, 다리, 허리는 일자로 있기 때문에 O(n)이지만, 머리는 (0,0) 부터 쭉 찾아서 처음 나오는
|
||||
*이므로 O(n^2)이다. 따라서 전체 시간 복잡도는 O(n^2)이다.
|
||||
|
||||
해설: (0,0)에서 선형으로 찾다가 가장 먼저 나오는 *이 머리이다. 이 머리 바로 한 칸 밑이 심장이다.
|
||||
심장에서 팔, 다리, 허리를 구하면 되는데, 연속된 *을 찾는 것이다.
|
||||
이는 행으로 연속된 별 찾기와 열로 연속된 별 찾기 함수 2개를 만들어서 진행하면 된다.
|
||||
위로 올라갈 일은 없어서 열은 그냥 down으로 했고, 행은 row로 방향을 인자로 받아서 체크했다.
|
||||
"""
|
||||
61
workbook_8708/silver/20310-s3.py
Normal file
61
workbook_8708/silver/20310-s3.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# 타노스
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
s = input().rstrip()
|
||||
|
||||
s_dict = {"0": [], "1": []}
|
||||
len_0 = 0
|
||||
len_1 = 0
|
||||
|
||||
for i in range(len(s)):
|
||||
if s[i] == "0":
|
||||
s_dict["0"].append(i)
|
||||
len_0 += 1
|
||||
else:
|
||||
s_dict["1"].append(i)
|
||||
len_1 += 1
|
||||
|
||||
len_0 //= 2
|
||||
len_1 //= 2
|
||||
|
||||
s_dict["0"] = deque(s_dict["0"][:len_0])
|
||||
s_dict["1"] = deque(s_dict["1"][len_1:])
|
||||
|
||||
new_s = ""
|
||||
|
||||
for _ in range(len_0+len_1):
|
||||
idx_0 = s_dict["0"][0] if len_0 > 0 else float('inf')
|
||||
idx_1 = s_dict["1"][0] if len_1 > 0 else float('inf')
|
||||
if idx_0 > idx_1:
|
||||
s_dict["1"].popleft()
|
||||
len_1 -= 1
|
||||
new_s += "1"
|
||||
else:
|
||||
s_dict["0"].popleft()
|
||||
len_0 -= 1
|
||||
new_s += "0"
|
||||
|
||||
|
||||
print(new_s)
|
||||
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: s길이만큼 개수를 세고, s길이의 반만큼 재배열을 하기 때문에 O(len(s))이다. 그런데 나처럼 popleft 하면서 하지 않고,
|
||||
그냥 두 리스트 합친다음에 sort하면 nlogn이므로 내가 더 낫다.
|
||||
|
||||
해설: 새로운 문자열 s는 기존 s에서 재배열 하는 것이 아니라 그냥 빼는 것이었다. 문제 설명 개별로네..
|
||||
아무튼 그래서 개수를 세고 1은 앞에 있는 것부터 반만큼 지우고, 0은 뒤에 있는 것부터 반만큼 지우면 된다.
|
||||
그렇게 하기 위해서 0과 1의 인덱스를 따로 기록해두고 0의 인덱스 리스트는 앞에서부터 반 자르고, 1은 반부터 뒤까지 자른다.
|
||||
마지막으로 이 인덱스 리스트 2개를 맨 앞에 것들끼리 비교해서 작은 놈을 popleft 하고, 그에 맞는 숫자(0 또는 1)을 new_s에 추가한다.
|
||||
deque는 슬라이스를 지원하지 않아서, 리스트에서 슬라이스하고 popleft 하기 전에 deque로 만들었다.
|
||||
"""
|
||||
55
workbook_8708/silver/2075-s3.py
Normal file
55
workbook_8708/silver/2075-s3.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# N번째 큰 수
|
||||
|
||||
import sys
|
||||
import heapq
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
rank = list(map(int, input().rstrip().split()))
|
||||
heapq.heapify(rank)
|
||||
for _ in range(n-1):
|
||||
nums = list(map(int, input().rstrip().split()))
|
||||
for i in range(n):
|
||||
heapq.heappush(rank, nums[i])
|
||||
heapq.heappop(rank)
|
||||
|
||||
print(heapq.heappop(rank))
|
||||
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분(메모리 때문에 고민 좀 했다.)
|
||||
|
||||
시간 복잡도: O(n^2logn) n^2개의 수를 읽을때마다 n개 길이의 힙에서 push와 pop을 하기 때문에 정렬 하는 것까지 logn해서 O(n^2logn)이다.
|
||||
|
||||
해설: 첫 번째 코드는 맨 마지막 행부터 n개중에 1등을 뽑고 1등이 나온 열에서 바로 한칸 위에 애를 데리고 또 n개중에 1등을 뽑고 총 n번을 진행하려고 했다.
|
||||
그런데 결국 이게 O(n^2)이라는 것을 깨닫고 여기서 n개 중에 1등을 뽑는 방식을 줄이기 위해 heap을 생각해냈다. 그러면 1등 뽑을 때 O(logn)에 할 수 있다.
|
||||
다른 문제가 하나 있는데 메모리 제한이 12MB라서 처음에 n^2개의 수들을 리스트에 저장하지 말고 한 줄씩 읽는대로 처리해야했다.
|
||||
따라서 한 줄씩 heap에 넣으며 1등만 데리고 다음 줄로 넘어가서 확인하는 방식으로 하려고 했는데 이건 마지막 라인에서 경합 자격도 없는 애가 승부를
|
||||
벌이게 되는 논리적 모순이 생기기 때문에 그냥 하나씩 계속 읽으면서 길이 n을 유지하는 최소 힙에 넣고 마지막에 heappop 하면 된다.
|
||||
"""
|
||||
|
||||
# def solution():
|
||||
# n = int(input().rstrip())
|
||||
|
||||
# nums = [[] for _ in range(n)]
|
||||
# for _ in range(n):
|
||||
# row = input().rstrip().split()
|
||||
# for i in range(n):
|
||||
# nums[i].append(int(row[i]))
|
||||
|
||||
# rank = [(-nums[i].pop(), i) for i in range(n)]
|
||||
# heapq.heapify(rank)
|
||||
|
||||
# for i in range(n-1):
|
||||
# _, nums_idx = heapq.heappop(rank)
|
||||
# heapq.heappush(rank, (-nums[nums_idx].pop(), nums_idx))
|
||||
|
||||
# print(-heapq.heappop(rank)[0])
|
||||
|
||||
# return
|
||||
59
workbook_8708/silver/20920-s3.py
Normal file
59
workbook_8708/silver/20920-s3.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# 영단어 암기는 괴로워
|
||||
|
||||
import sys
|
||||
import heapq
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def set_priority(words, word):
|
||||
word_info = words.get(word, None)
|
||||
frequency, length = 0, 0
|
||||
if word_info:
|
||||
frequency = -(word_info[0]) + 1
|
||||
length = -(word_info[1])
|
||||
else:
|
||||
frequency = 1
|
||||
length = len(word)
|
||||
|
||||
words[word] = [-frequency, -length, word, 0]
|
||||
return words[word]
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
words = {}
|
||||
|
||||
word_list = []
|
||||
|
||||
for i in range(n):
|
||||
word = input().rstrip()
|
||||
|
||||
if len(word) < m:
|
||||
continue
|
||||
|
||||
heapq.heappush(word_list, set_priority(words, word))
|
||||
|
||||
for i in range(len(word_list)):
|
||||
f, l, w, is_pop = heapq.heappop(word_list)
|
||||
if words.get(w)[3]:
|
||||
continue
|
||||
else:
|
||||
print(w)
|
||||
words[w][3] = 1
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 35분
|
||||
|
||||
시간 복잡도: set_priority는 단어 길이를 세고, 정보를 dict에서 읽고 쓰는 것인데 m은 최대 10이므로 전체 시간복잡도는 O(1)이다.
|
||||
solution 함수에서 n개의 단어를 보며 set_priority를 실행하고, heap에 push하므로 요소당 O(logn)이기 때문에 O(nlogn)이다.
|
||||
마지막으로 word_list를 확인할 때도 heap에서 pop이므로 O(nlogn)이다. 따라서 전체 시간복잡도는 O(nlogn)이다.
|
||||
|
||||
해설: heap에서 정렬할 때 우선순위 3가지로 정렬하도록 리스트를 넣는다.
|
||||
그러기 위해 word_info dict을 만들어서 정보 업데이트를 O(1)에 한다.
|
||||
단어마다 정보를 업데이트 해가며 heap에 넣고, 다 넣은 다음 heappop 하면서 기존에 안 나온 것들만 출력을 한다.
|
||||
좀 빠르게 해보겠다고 heap 써서 O(nlogn)으로 했지만 그냥 Counter 하고, 우선순위 역순으로 sort 3번 하면 이것도 O(nlogn)이다...
|
||||
"""
|
||||
44
workbook_8708/silver/20922-s1.py
Normal file
44
workbook_8708/silver/20922-s1.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# 겹치는 건 싫어
|
||||
|
||||
import sys
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
s = list(map(int, input().rstrip().split()))
|
||||
|
||||
idx = 0
|
||||
c = {}
|
||||
d = deque([])
|
||||
result = 0
|
||||
while idx < len(s):
|
||||
new = s[idx]
|
||||
if not c.get(new, 0):
|
||||
c[new] = 0
|
||||
d.append(new)
|
||||
c[new] += 1
|
||||
if c[new] > k:
|
||||
while d and c[new] > k:
|
||||
now = d.popleft()
|
||||
c[now] -= 1
|
||||
result = max(result, len(d))
|
||||
idx += 1
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 15분
|
||||
|
||||
시간 복잡도: 한 요소가 deque에 들어갔다가 나오기를 한번씩만 하므로 O(n)이다.
|
||||
|
||||
해설: deque에 숫자를 넣고, 숫자마다 개수를 dict로 센다.
|
||||
숫자를 deque에 넣었을 때 그 숫자의 개수가 k개를 넘으면 그 숫자가 k개 이하가 될때까지 deque에서 popleft를 한다.
|
||||
매번 현재 길이를 최대 길이와 비교해간다.
|
||||
"""
|
||||
38
workbook_8708/silver/2164-s4.py
Normal file
38
workbook_8708/silver/2164-s4.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# 카드2
|
||||
|
||||
import sys
|
||||
|
||||
from collections import deque
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
cards = deque([i for i in range(1, n+1)])
|
||||
|
||||
drop_count = 0
|
||||
while drop_count < n-1:
|
||||
cards.popleft()
|
||||
drop_count += 1
|
||||
cards.append(cards.popleft())
|
||||
|
||||
print(cards.pop())
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 13분
|
||||
|
||||
시간 복잡도: deque에 넣고 빼는 작업은 O(1)이므로, 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: deque에 넣고 진행할 경우 앞, 뒤에 대한 추가, 삭제 연산이 O(1)이므로 이 자료구조를 활용해서 상황을 그대로 구현하면 된다.
|
||||
|
||||
규칙을 좀 찾아보면 먼저 홀수를 다 버리고, 짝수만 남은 상태에서 또 지워나가는 규칙을 찾을 수 있어서 수학적으로 풀 수 있을 것 같지만,
|
||||
이 문제를 서비스 자체라고 생각하면 조건이 어떻게 바뀔지 모르는 상태에서 규칙을 찾아서 그 규칙에만 맞는 코드를 짜는 것보다는
|
||||
시뮬레이션쪽으로 설계함으로써 사람이 하기 힘든 반복 작업을 자동화하는 것이 더 목적성이 맞다고 생각한다.
|
||||
"""
|
||||
46
workbook_8708/silver/21921-s3.py
Normal file
46
workbook_8708/silver/21921-s3.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# 블로그
|
||||
|
||||
import sys
|
||||
|
||||
from collections import deque, Counter
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, x = map(int, input().rstrip().split())
|
||||
|
||||
one_days = list(map(int, input().rstrip().split()))
|
||||
duration = deque([one_days[i] for i in range(x)])
|
||||
|
||||
duration_result = [0] * n
|
||||
duration_result[x-1] = sum(duration)
|
||||
|
||||
for i in range(x, n):
|
||||
before = duration.popleft()
|
||||
duration.append(one_days[i])
|
||||
after = duration[-1]
|
||||
duration_result[i] = duration_result[i-1] - before + after
|
||||
|
||||
c = Counter(duration_result)
|
||||
max_vistor = max(c)
|
||||
if max_vistor == 0:
|
||||
print('SAD')
|
||||
else:
|
||||
print(max_vistor)
|
||||
print(c.get(max_vistor))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 19분
|
||||
|
||||
시간 복잡도: 전체 요소를 한, 두바퀴 정도 돌기 때문에 O(n)이다.
|
||||
|
||||
해설: 그냥 인덱스로 앞 뒤로 줄이고, 늘이면 되는데 슬라이딩 윈도우는 deque를 쓰는게 좀 직관적이라서 deque를 사용했다.
|
||||
최대값과 count를 계속 업데이트 하는 것이 코드가 가독성이 떨어지는 것 같아서 어차피 그렇게 연산하는 것과
|
||||
마지막에 결과 리스트 한 바퀴 돌면서 개수 세는 연산이 비슷하기 때문에 그냥 결과 리스트에 쭉 저장하고 Counter로 개수를 셌다.
|
||||
0이 최대일 경우 SAD 출력(처음에 이거 안해서 틀림), 아니면 최대값과 그 개수를 출력한다.
|
||||
"""
|
||||
38
workbook_8708/silver/22233-s3.py
Normal file
38
workbook_8708/silver/22233-s3.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# 가희와 키워드
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, m = map(int, input().rstrip().split())
|
||||
|
||||
memo = set()
|
||||
|
||||
for _ in range(n):
|
||||
memo.add(input().rstrip())
|
||||
|
||||
for _ in range(m):
|
||||
for keyword in input().rstrip().split(","):
|
||||
if keyword in memo:
|
||||
memo.remove(keyword)
|
||||
|
||||
print(len(memo))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 20분
|
||||
|
||||
시간 복잡도: 한 글에 최대 키워드가 10개이므로, set으로 차집합을 구하면 두 집합 중 작은 것만큼 시간이 드는데,
|
||||
작은 것의 최대 길이가 10이므로 O(10m)이다. set의 길이는 key의 개수이므로 O(1)이기 때문이다.
|
||||
|
||||
해설: 처음에는 memo - keyswords를 했는데 이 연산은 비파괴 연산이라 기존 set들을 유지해야하므로
|
||||
차집합된 set을 새로 만든다. 따라서 memo 길이만큼의 시간이 든다.
|
||||
그래서 in으로 있는지 확인(O(1))하고, remove(O(1))로 지웠다.
|
||||
remove는 key가 없으면 keyerror가 나는데 그래서 나는 있을 때만 지워서 괜찮았고,
|
||||
discard를 쓰면 있으면 지우고 없으면 그냥 가만히 있는다고 한다.
|
||||
"""
|
||||
59
workbook_8708/silver/2304-s2.py
Normal file
59
workbook_8708/silver/2304-s2.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# 창고 다각형
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
line = sorted([tuple(map(int, input().rstrip().split())) for _ in range(n)])
|
||||
|
||||
high_stack = []
|
||||
result = 0
|
||||
|
||||
for x, y in line:
|
||||
if not high_stack:
|
||||
high_stack.append((x, y))
|
||||
continue
|
||||
|
||||
last_pop = ()
|
||||
while len(high_stack) != 0 and high_stack[-1][1] <= y:
|
||||
last_pop = high_stack.pop()
|
||||
|
||||
if len(high_stack) == 0:
|
||||
result += (x - last_pop[0])*last_pop[1]
|
||||
|
||||
high_stack.append((x, y))
|
||||
|
||||
for _ in range(len(high_stack)):
|
||||
x, y = high_stack.pop()
|
||||
if len(high_stack) == 0:
|
||||
result += y
|
||||
else:
|
||||
result += (x - high_stack[-1][0])*y
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: while문이 있지만 어차피 전체적으로는 요소 기준으로 봤을 때 stack에 들어가고 나오는거 한번씩이기 때문에 O(n)이다.
|
||||
|
||||
해설: 가장 높은 놈(top)을 만날때까지는 그냥 max 갱신해가며 하면 되지만 내리막에서는 작은 놈을 갱신하며 가야된다.
|
||||
근데 내려갈때 무지성으로 작은 놈만 갱신해가면, 갑자기 큰 놈이 나왔을 때 우물형태가 생기므로 조건에 위배되기 때문에 지금까지 구했던것을 다시 계산해야된다.
|
||||
근데 그러면 돌아가서 다시 계산하기 때문에 O(n^2)이 되버린다.
|
||||
따라서 작은 놈을 계속 가져가되, 그것보다 큰 놈이 나왔을 때 이전 작은 것들을 버리는 방식으로 하면 된다. 이건 stack을 쓰면 쉽게 구현이 가능하다.
|
||||
따라서 스택에 넣는 조건을 내가 들어갈때 스택에(이전 놈들) 나보다 작은 애들은 다 pop하고 들어간다. 그렇게 끝에는 top과 완벽한 내리막만 남는다.
|
||||
이제 stack에서 pop을 하면서 pop한 녀석과 아직 stack에 남아있는 놈과의 거리로 넓이를 계산하고 마지막에 나오는 녀석은 너비가 1이므로 계산하면 된다.
|
||||
한 가지 문제는 오르막에서도 이 조건을 그대로 쓰면 나보다 작은 이전 놈들의 권리가 없어진다.
|
||||
따라서 내가 스택에 들어갈 때 나보다 작은 놈들을 다 pop했는데 stack이 비어 있다면 아직 top이 없었던 것이기 때문에 마지막에 나온 애는 넓이를 계산해준다.
|
||||
|
||||
다른 풀이로는 가장 높은 놈을 기준으로 오르막과 내리막이 나올 수밖에 없으므로, 왼쪽에서 top까지 max를 갱신해가며 넓이 구하고,
|
||||
오른쪽에서 top까지 반대로 가면서 max 갱신해가며 넓이 구해서 더하면 끝이긴 하네.
|
||||
"""
|
||||
56
workbook_8708/silver/2512-s2.py
Normal file
56
workbook_8708/silver/2512-s2.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# 예산
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
req = list(map(int, input().rstrip().split()))
|
||||
|
||||
m = int(input().rstrip())
|
||||
|
||||
if sum(req) <= m:
|
||||
print(max(req))
|
||||
return
|
||||
|
||||
now_ceil = m // n
|
||||
now_asset = m
|
||||
sorted_req = sorted(req)
|
||||
idx = 0
|
||||
|
||||
while idx < n-1 and now_ceil >= sorted_req[idx]:
|
||||
now_asset -= sorted_req[idx]
|
||||
idx += 1
|
||||
now_ceil = now_asset // (n-idx)
|
||||
|
||||
print(now_ceil)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 1시간 10분
|
||||
|
||||
시간 복잡도: 내 풀이는 정렬할 때 O(nlogn)이고, n개의 요청예산을 보기 때문에 O(n)이라서 전체 시간복잡도는 O(nlogn)이다.
|
||||
이분탐색 풀이의 경우는 0부터 max(req) 범위에서 찾기 때문에 log(max(req))이고, 매 mid마다 req 내용을 다 확인하므로
|
||||
O(nlog(max(req)))이다.
|
||||
문제에서는 req <= 10^5이고, n <= 10000이기 때문에 log로 치면 내가 더 빠르지만 이 조건이 바뀌는 것에 따라 달라질 것 같다.
|
||||
|
||||
해설: 요청 예산의 합이 m보다 작거나 같다면 그냥 다 주고 요청 예산 중 최대값을 출력하면 된다.
|
||||
근데 아니라면 두 가지 풀이 방법이 있다.
|
||||
먼저 내가 처음 푼 방식은 요청 예산들을 오름차순으로 정렬한 후 처음 상한액을 평균값으로 매긴다.
|
||||
그 다음 한 곳씩 예산을 나눠주는데 이때 상한액 이하의 곳들은 나눠주고 남은 예산으로 남은 곳의 수를 나눠서 다시 평균값을 상한액으로 바꾼다.
|
||||
이 과정을 반복하다가 현재 상한액보다 많은 곳을 요청한 곳이 있으면 앞으로 뒤에 있는 곳들도 요청한만큼 채워줄 수 없기 때문에
|
||||
이번 상한액이 답이다.
|
||||
|
||||
근데 이분탐색으로 푸는 방법이 있음.
|
||||
전체 요청 예산의 범위 중 상한액을 이분 탐색으로 찾아가는 것임.
|
||||
한 점을 찾는 것이기 때문에 l <= r 조건에서 [mid]를 설정하고, n개의 요청 예산을 설정한 mid 기준으로 다 분배해본 후,
|
||||
m 이하 중 최대값을 찾으면 된다.
|
||||
s를 그때그때 결과라고 하면, 오름차순 정렬에서 s가 m 이하인 경우를 찾는 것이기 때문에 s <= m 이면 답이 될 수 있고,
|
||||
오른쪽을 찾아봐야하기 때문에 l = mid라고 생각할 수 있지만, 이것은 들어갈 곳이 아닌 한 점을 찾는 것이기 때문에
|
||||
l <= r을 한 이상 안 끝날 수도 있다. 따라서 mid는 따로 기록해두고, l = mid + 1, r= mid - 1로 해가며 찾아야한다.
|
||||
"""
|
||||
40
workbook_8708/silver/2531-s1.py
Normal file
40
workbook_8708/silver/2531-s1.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# 회전 초밥
|
||||
|
||||
import sys
|
||||
from collections import Counter
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, d, k, c = map(int, input().rstrip().split())
|
||||
|
||||
belt = [int(input().rstrip()) for _ in range(n)]
|
||||
double_belt = belt + belt
|
||||
|
||||
eat = Counter(belt[:k])
|
||||
eat.setdefault(c, 0)
|
||||
eat[c] += 1
|
||||
result = len(eat)
|
||||
for i in range(1, len(double_belt)-k+1):
|
||||
eat[double_belt[i-1]] -= 1
|
||||
if eat[double_belt[i-1]] == 0:
|
||||
del eat[double_belt[i-1]]
|
||||
eat.setdefault(double_belt[i+k-1], 0)
|
||||
eat[double_belt[i+k-1]] += 1
|
||||
result = max(result, len(eat))
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 24분
|
||||
|
||||
시간 복잡도: 2n 길이의 리스트를 1번 순회하고, 그 과정에서 처리는 dict로 O(1)이므로, 전체 시간복잡도는 O(n)이다.
|
||||
|
||||
해설: 같은 두 리스트를 이어붙여서 원형을 만든 후 k 구간씩 슬라이딩하면서 다른 종류의 개수를 세면 된다.
|
||||
각 음식마다 있는 개수는 dict에 저장하고, key의 개수 세기로 O(1)에 종류 개수를 세기 때문에 value가 0이면 del로 key까지 없앤다.
|
||||
"""
|
||||
29
workbook_8708/silver/25757-s5.py
Normal file
29
workbook_8708/silver/25757-s5.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# 임스와 함께하는 미니게임
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
game_types = {"Y": 2, "F": 3, "O": 4}
|
||||
|
||||
def solution():
|
||||
q = list(input().rstrip().split())
|
||||
n, personnel = int(q[0]), game_types.get(q[1], 0)
|
||||
people = set()
|
||||
for _ in range(n):
|
||||
people.add(input().rstrip())
|
||||
result = len(people) // (personnel-1)
|
||||
print(result)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 18분
|
||||
|
||||
시간 복잡도: 사람들 이름을 쭉 읽고, 쓰고, set() 개수 세는 것까지 n이므로 전체 시간복잡도는 O(n)
|
||||
|
||||
해설: 한 사람이 임스와 두 번 게임을 할 수는 없으므로 참여 명단을 중복을 제거하는 set()을 활용한다.
|
||||
그 후 임스 본인을 제외한 게임에 필요한 인원 수로 set() 길이를 나누면 몫이 임스가 할 수 있는 게임 수이다.
|
||||
"""
|
||||
63
workbook_8708/silver/2607-s2.py
Normal file
63
workbook_8708/silver/2607-s2.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# 비슷한 단어
|
||||
|
||||
import sys
|
||||
from collections import Counter
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def check_similar(now_word, target_c):
|
||||
target_c_copy = target_c.copy()
|
||||
now_word_left = []
|
||||
for c in now_word:
|
||||
if len(target_c_copy) < 1:
|
||||
break
|
||||
|
||||
if target_c_copy.get(c, -1) == -1:
|
||||
now_word_left.append(c)
|
||||
continue
|
||||
|
||||
target_c_copy[c] -= 1
|
||||
if target_c_copy[c] == 0:
|
||||
del target_c_copy[c]
|
||||
|
||||
len_target_left = sum(target_c_copy.values())
|
||||
result = 1 if len_target_left <= 1 and len(now_word_left) <= 1 else 0
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
result = 0
|
||||
target = input().rstrip()
|
||||
target_c = Counter(target)
|
||||
|
||||
for _ in range(n-1):
|
||||
now_word = input().rstrip()
|
||||
if len(now_word) >= len(target)+2:
|
||||
continue
|
||||
|
||||
result += check_similar(now_word, target_c)
|
||||
|
||||
print(result)
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 32분
|
||||
|
||||
시간 복잡도: 단어 길이를 m이라고 하자. 중복 제거할 때는 둘 중 짧은 단어만큼 진행된다. -> O(m)
|
||||
target_c의 values 합 구하기 -> O(m)
|
||||
이 두 과정이 check_similar()이고, O(m)이다. 이제 이 과정을 n-1개의 단어만큼 진행하기 때문에 전체 시간복잡도는 O(nm)이다.
|
||||
|
||||
해설: 비슷한 단어의 조건을 수치적으로 정리하면 target과 비교하는 단어의 길이 차이가 2이상 나면 안되고,
|
||||
겹치는 글자들을 개수 기준으로 다 제거했을 때 양쪽 다 남은 글자가 1을 초과하면 안된다.
|
||||
따라서 나는 target을 Counter로 만들고, 비교하는 단어를 쭉 보면서 target_c에 있으면 개수를 줄이는 방식으로 중복을 제거했다.
|
||||
이때 target_c에 없으면 남는 글자는 따로 리스트에 보관하였다.
|
||||
마지막으로 target_c의 values 합이 남는 글자 수고, len(lst)가 비교하는 글자의 남는 글자 수이므로 이것의 길이가 둘 다 <= 1일때만
|
||||
비슷한 단어로 판정했다.
|
||||
"""
|
||||
63
workbook_8708/silver/3758-s2.py
Normal file
63
workbook_8708/silver/3758-s2.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# KCPC
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
|
||||
def write_board(board, i, j, s, idx):
|
||||
if not board.get(i, 0):
|
||||
board[i] = {"problems": {}, "submit_count": 0, "last_submit": -1}
|
||||
|
||||
board[i]["problems"][j] = max(board[i]["problems"].get(j, 0), s)
|
||||
board[i]["submit_count"] += 1
|
||||
board[i]["last_submit"] = idx
|
||||
|
||||
return
|
||||
|
||||
def check_our_rank(board, t):
|
||||
ranking = []
|
||||
for k in board:
|
||||
info = (k, -sum(board[k]["problems"].values()), board[k]["submit_count"], board[k]["last_submit"])
|
||||
ranking.append(info)
|
||||
|
||||
ranking.sort(key=lambda x: (x[1], x[2], x[3]))
|
||||
|
||||
for i, record in enumerate(ranking):
|
||||
if record[0] == t:
|
||||
return i+1
|
||||
|
||||
def test(n ,k ,t, m):
|
||||
board = {} # 팀id: {문제: {번호: 점수}, 제출 횟수: ~, 마지막 제출 인덱스: ~}
|
||||
for idx in range(m):
|
||||
i, j, s = map(int, input().rstrip().split())
|
||||
write_board(board, i, j, s, idx)
|
||||
|
||||
return check_our_rank(board, t)
|
||||
|
||||
|
||||
|
||||
def solution():
|
||||
T = int(input().rstrip())
|
||||
for _ in range(T):
|
||||
n, k, t, m = map(int, input().rstrip().split())
|
||||
print(test(n, k, t, m))
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분
|
||||
|
||||
시간 복잡도: write_board가 O(1), check_our_rank가 sort때문에 O(nlogn)이므로, 이 둘을 활용한 test는 O(nlogn)이다.
|
||||
따라서 전체 시간복잡도는 test하는 횟수를 곱해서 O(Tnlogn)이다.
|
||||
|
||||
해설: 문제에서 시키는대로 구현하면 된다. 순위를 정하기 위해 마지막에 정렬해야 하는데 기준이 되는 요소들이
|
||||
최종 점수 > 제출 횟수 > 마지막 제출 시간이기 때문에 이 정보들을 dict에 기록하면서 진행하기로 했다.
|
||||
최종 점수를 계속 갱신하는 것이 신경쓸 것이 좀 있어서 마지막에 한번에 모아서 계산하는거랑 그때그때 갱신하는 거랑 시간복잡도는 같다고
|
||||
판단하여 마지막에 계산하였다.
|
||||
그 후 팀 id와 3가지 요소를 튜플로 묶어서 리스트에 넣은 다음 lambda를 활용하여 sort 하였다.
|
||||
동순위는 없으므로 팀 id가 t인 튜플의 인덱스+1을 한 것이 답이다.
|
||||
"""
|
||||
65
workbook_8708/silver/4659-s5.py
Normal file
65
workbook_8708/silver/4659-s5.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# 비밀번호 발음하기
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
alphabet = "abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
VOWEL = "aeiou"
|
||||
CONSONANT_OR_VOWEL = {a: 0 for a in alphabet} # 0이면 자음, 1이면 모음
|
||||
for v in VOWEL:
|
||||
CONSONANT_OR_VOWEL[v] = 1
|
||||
|
||||
def check_word(word):
|
||||
is_vowel_in = False
|
||||
sequence_count = [-1, 0] # sequence_count[0]은 자음(0),모음(1) 구분, sequence_count[1]은 count
|
||||
before_w = ""
|
||||
for w in word:
|
||||
if not is_vowel_in and CONSONANT_OR_VOWEL[w] == 1: # 1번째 조건
|
||||
is_vowel_in = True
|
||||
|
||||
if sequence_count[0] == CONSONANT_OR_VOWEL[w]: # 2번째 조건
|
||||
sequence_count[1] += 1
|
||||
if sequence_count[1] >= 3:
|
||||
return False
|
||||
else:
|
||||
sequence_count[0], sequence_count[1] = CONSONANT_OR_VOWEL[w], 1
|
||||
|
||||
if before_w not in ("e", "o") and before_w == w: # 3번째 조건
|
||||
return False
|
||||
before_w = w
|
||||
|
||||
if not is_vowel_in: # 1번째 조건 최종 확인
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def solution():
|
||||
while 1:
|
||||
word = input().rstrip()
|
||||
if word == "end":
|
||||
break
|
||||
|
||||
is_acceptable = check_word(word)
|
||||
|
||||
if is_acceptable:
|
||||
print(f"<{word}> is acceptable.")
|
||||
else:
|
||||
print(f"<{word}> is not acceptable.")
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분
|
||||
|
||||
시간 복잡도: 들어오는 모든 단어의 길이만큼의 시간이 걸린다.
|
||||
|
||||
해설: 자음과 모음 여부를 dictionary에 1, 0으로 O(1)에 구분할 수 있도록 세팅을 해둔다.
|
||||
1번 조건은 한글자씩 볼 때 모음 여부에 따라 is_vowel_in 진위 여부를 결정한다.
|
||||
2번 조건은 어떤 것이 몇 번 연속되고 있는지 현황을 기록하는 길이 2 리스트를 만들어서 판단한다. 기록과 다른 것이 나오면 초기화한다.
|
||||
3번 조건은 이전 단어를 저장하는 변수를 만들고 이전 단어가 "e", "o"이면 통과하고, 아닐 경우 2번 연속되는지 확인한다.
|
||||
"""
|
||||
35
workbook_8708/silver/8979-s5.py
Normal file
35
workbook_8708/silver/8979-s5.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# 올림픽
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n, k = map(int, input().rstrip().split())
|
||||
records = [0] * n
|
||||
for _ in range(n):
|
||||
a, b, c, d = map(int, input().rstrip().split())
|
||||
records[a-1] = (b,c,d)
|
||||
|
||||
ordered_records = sorted(records, key=lambda x:(-x[0], -x[1], -x[2]))
|
||||
target = records[k-1]
|
||||
rank = 0
|
||||
while 1:
|
||||
now = (ordered_records[rank][0], ordered_records[rank][1], ordered_records[rank][2])
|
||||
if now == target:
|
||||
break
|
||||
rank += 1
|
||||
|
||||
print(rank+1)
|
||||
return
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 40분(dictionary 써서 더 좋게 해보려다가 늦음..)
|
||||
|
||||
시간 복잡도: nlogn(정렬) + kn(기록, 탐색) => O(nlogn)
|
||||
|
||||
해설: k를 인덱스에 맞춰서 records에 메달만 튜플로 넣는다.
|
||||
records를 메달 규칙에 맞게 정렬 후 while로 타켓 튜플을 처음 찾고 +1 하면 그것이 그 그룹의 등수이다.
|
||||
"""
|
||||
79
workbook_8708/silver/9017-s3.py
Normal file
79
workbook_8708/silver/9017-s3.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# 크로스 컨트리
|
||||
|
||||
import sys
|
||||
|
||||
from collections import Counter
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def exclude_team(teams):
|
||||
excluded = set()
|
||||
|
||||
for team in teams:
|
||||
if teams[team] != 6:
|
||||
excluded.add(team)
|
||||
|
||||
return excluded
|
||||
|
||||
def find_winning_team(rank, excluded, team_count, n):
|
||||
team_score = {i: {"count": 0, "score": 0} for i in range(1, team_count+1) if i not in excluded}
|
||||
first_5th = {}
|
||||
now_rank = 0
|
||||
for r in rank:
|
||||
if r in excluded:
|
||||
continue
|
||||
|
||||
now_rank += 1
|
||||
|
||||
if team_score[r]["count"] >= 4:
|
||||
if first_5th.get(r, 0) == 0:
|
||||
first_5th[r] = now_rank
|
||||
continue
|
||||
team_score[r]["score"] += (now_rank)
|
||||
team_score[r]["count"] += 1
|
||||
|
||||
winner = {"team": 0, "score": float("inf"), "5th": n+1}
|
||||
for team in team_score:
|
||||
if team_score[team]["score"] < winner["score"]:
|
||||
winner["team"], winner["score"], winner["5th"] = team, team_score[team]["score"], first_5th.get(team, n+1)
|
||||
elif team_score[team]["score"] == winner["score"] and first_5th.get(team, n+1) < winner["5th"]:
|
||||
winner["team"], winner["score"], winner["5th"] = team, team_score[team]["score"], first_5th.get(team, n+1)
|
||||
else:
|
||||
continue
|
||||
|
||||
return winner["team"]
|
||||
|
||||
|
||||
def game():
|
||||
n = int(input().rstrip())
|
||||
rank = list(map(int, input().rstrip().split()))
|
||||
teams = Counter(rank)
|
||||
excluded = exclude_team(teams)
|
||||
|
||||
result = find_winning_team(rank, excluded, len(teams), n)
|
||||
|
||||
return result
|
||||
|
||||
def solution():
|
||||
t = int(input().rstrip())
|
||||
for _ in range(t):
|
||||
result = game()
|
||||
print(result)
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 50분 정도(score를 반대로 생각하거나, dictionary keyerror 때문에..) -> dict는 앵간하면 .get()으로 하자.
|
||||
|
||||
시간 복잡도: exclude_team()은 Counter 객체 전체를 순회하기 때문에 O(m)이다.
|
||||
find_winning_team()은 rank 전체를 순회하고 팀 리스트를 순회하는 것인데 set과 dict를 쓰므로 O(1)이라서 전체는 m < n이므로 O(n)이다.
|
||||
game()은 Counter이므로 O(m)에다가 exclude_team()과 find_winning_team()을 돌리기 때문에 전체는 O(n)이다.
|
||||
마지막으로 전체 프로그램은 game()을 t번 반복하기 때문에 전체 시간복잡도는 O(t*n)이다.
|
||||
함수별로 나눠놓으니까 전체 시간복잡도를 계산하는 것이 확실히 편하다.
|
||||
|
||||
해설: 먼저 6명이 아닌 팀을 counter로 알아낸 뒤 제외한다. 그 후 rank 리스트를 순차적으로 확인하면서 팀의 총점을 기록한다.
|
||||
이때, 4등까지만 계산을 하도록 조건을 걸어주고, 팀의 5등이 전체 몇 등인지만 dict에 저장한다.
|
||||
마지막에 총점을 비교하고, 같다면 5등까지 확인하는 절차를 거쳐서 최종 우승 팀을 결정한다.
|
||||
"""
|
||||
38
workbook_8708/silver/9655-s5.py
Normal file
38
workbook_8708/silver/9655-s5.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# 돌 게임
|
||||
|
||||
import sys
|
||||
|
||||
input = sys.stdin.readline
|
||||
|
||||
def solution():
|
||||
n = int(input().rstrip())
|
||||
|
||||
print("SK") if n%2 == 1 else print("CY")
|
||||
|
||||
return
|
||||
|
||||
|
||||
solution()
|
||||
|
||||
"""
|
||||
걸린 시간: 25분(dp로도 풀 수 있을 것 같아서 고민하다가..)
|
||||
|
||||
시간 복잡도: 그냥 % 계산 한번이니까 O(1)이다.
|
||||
|
||||
해설: 마지막에 무조건 창영이가 가져가기 때문에 상근이가 이기려면 돌을 남겨두면 안된다.
|
||||
완벽하게 게임을 한다는 이야기는 서로 이기기 위해 최선을 다한 수만 생각한다.
|
||||
k번째에 경기가 끝난다고 할 때, 상근이가 이기려면 k-1번째에 경기가 끝났을 때 1, 3개 중에 남아야 하고, 0, 2개가 남으면 창영이가 이긴다.
|
||||
한 경기가 끝나면 2 or 4 or 6개의 돌이 없어지므로, 무조건 짝수개씩 사라지기 때문에 n이 짝수면 홀수개 즉, 1,3개가 절대 남을 수 없다.
|
||||
반대도 마찬가지이므로 n이 짝수면 창영이의 승리, n이 홀수면 상근이의 승리이다.
|
||||
|
||||
dp로 만들어보면 dp[i]는 i개의 돌이 있을 때 상근이의 승리 여부이다. (dp[i]=1 -> 상근이 승리)
|
||||
|
||||
dp[i-1]에서 상근이가 이겼다면 1개 가져와서 이긴 경우, dp[i]는 1개가 남으므로 창영이 승리
|
||||
dp[i-1]에서 상근이가 이겼다면 3개 가져와서 이긴 경우, dp[i]는 4개가 남으므로 어떻게 해도 창영이 승리
|
||||
dp[i-1]에서 상근이가 진 상황도 위와 그대로 반대이다. 따라서 dp[i] = 1-dp[i-1]
|
||||
|
||||
초기 dp는 0번째만 필요하므로 dp[0]=1 (돌이 1개이고, 상근이가 시작하니까)
|
||||
|
||||
dp[i]의 적절한 상황을 구성하고, i상황이 되기 위해 연관되는 i 이전의 상황들을 상정하여 dp 식을 세우면 된다.
|
||||
이번 상황은 i-1번째 상황만으로 i번째 상황이 결정된다.
|
||||
"""
|
||||
Reference in New Issue
Block a user