후기/대회

Codeforces Round 855 (Div. 3) (버츄얼)

beans3142 2023. 3. 19. 16:22

 

결과

 

A번 풀이

문제

https://codeforces.com/contest/1800/problem/A

 

Problem - A - Codeforces

 

codeforces.com

알고리즘 분류 

문자열, 구현

 

풀이

딱 보자마자 어떤 문제인지는 감이 왔다.

그런데 막상 구현하려니 생각보다 애를 많이 먹었다.

결과적으로는 스택을 이용해서 풀어주었지만 분명 더 좋은 풀이가 있을 것이란 생각이 든다.

 

m, e, o, w 중 하나라면 스택의 맨 위의 값과 비교해서 넣거나 넣지 않는다.

결국 순서대로 알맞게 들어갔다면 스택 안에는 4개의 값만 들어있을 것이고 그것이 정답 배열과 같다면 "YES" 아니면 "NO 를 출력해주었다.

from sys import stdin
input=stdin.readline
for i in range(int(input())):
    n=int(input())
    s=[i.lower() for i in input().rstrip()]
    order=['w','o','e','m']
    idx=0
    st=[]
    while s:
        now=s.pop()
        if st and st[-1]==now and now in order:
            pass
        else:
            st.append(now)
    if st==order:
        print('YES')
    else:
        print('NO')

 

B번 풀이

문제

https://codeforces.com/contest/1800/problem/B

 

Problem - B - Codeforces

 

codeforces.com

알고리즘 분류 

그리디, 문자열

 

풀이

조금 고민을 했던 문제이다.

일단 각 알파뱃의 대문자와 소문자의 개수를 저장해준 뒤 각 알파벳의 min(대문자의 개수, 소문자의 개수) 만큼 더해서 k번의 변경 없는 상태에서의 쌍의 개수를 구할 수 있다.

 

그리고 대문자의 개수와 소문자의 개수의 차이를 이용해서 정답을 구해주면 된다. 대문자의 개수가 하나 늘거나 줄 때 소문자의 개수는 하나 줄거나 늘게 된다는 사실을 명심해야 한다.

 

따라서 대소문자 개수 차이의 // 2만큼 k번 바꿔주면 답을 구할 수 있다.

from sys import stdin
input=stdin.readline

for _ in range(int(input())):
    n,k=map(int,input().split())
    s=input().rstrip()
    l=[0]*26
    u=[0]*26
    for i in range(n):
        if s[i].isupper():
            u[ord(s[i])-65]+=1
        else:
            l[ord(s[i])-97]+=1
    ans=0
    for i in range(26):
        if abs(l[i]-u[i])//2<=k:
            k-=abs(l[i]-u[i])//2
            l[i]=u[i]=abs(l[i]-u[i])//2+min(l[i],u[i])
        else:
            l[i]=u[i]=min(l[i],u[i])+k
            k=0
        ans+=min(l[i],u[i])
    print(ans)

 

C(1,2)번 풀이

문제

https://codeforces.com/contest/1800/problem/C1

 

Problem - C1 - Codeforces

 

codeforces.com

https://codeforces.com/contest/1800/problem/C2

 

Problem - C2 - Codeforces

 

codeforces.com

알고리즘 분류 

그리디

풀이

스택+우선순위 큐로 해결했다.

살짝 뇌절한 부분이 있었지만 일단 중요한 것은 영웅 카드를 뽑기 전까지 얻은 보너스 카드중 가장 큰 카드들만 사용하면 된다.

이 때 적절한 방법을 이용해서 이전까지 나온 카드 중 가장 큰 값을 계속 맨 위로 올려주면 된다.

나는 스택과 우선순위 큐를 이용해주었다.

 

from sys import stdin
from heapq import heappush,heappop
input=stdin.readline

for _ in range(int(input())):
    n=int(input())
    deck=list(map(int,input().split()))
    bonusdeck=[]
    ans=0
    discard=[]
    for i in range(n):
        if deck[i]==0:
            if bonusdeck and discard:
                if bonusdeck[-1]<-discard[0]:
                    ans-=heappop(discard)
                else:
                    ans+=bonusdeck.pop()
            elif bonusdeck:
                ans+=bonusdeck.pop()
            elif discard:
                ans-=heappop(discard)
        else:
            if bonusdeck:
                if bonusdeck[-1]<=deck[i]:
                    bonusdeck.append(deck[i])
                else:
                    heappush(discard,-deck[i])
            else:
                bonusdeck.append(deck[i])
    print(ans)

 

D번 풀이

문제

https://codeforces.com/contest/1800/problem/D

 

Problem - D - Codeforces

 

codeforces.com

알고리즘 분류 

그리디, 문자열, 자료구조

 

풀이

연속된 2개의 문자를 지웠을 때 나오는 경우의 수를 구하는 문제이다.

연속된 글자를 지웠을 때 같은 결과가 나오는 경우를 생각해보았다.

글자 3개가 있을 때 모두 같은 경우(aaa) 어떤 2개를 지워도 다 같은 결과이다. 앞 뒤만 같은 경우 (aba) 마찬가지로 어떤 2개를 지워도 다 같은 결과이다.

따라서 이전에 지운 문자열과 비교를 해서 set(s[i-1]+s[i]) == set(s[i]+s[i+1]) 인 경우 이전에 지운 것과 동일한 결과를 낳는다.

 

from sys import stdin
from math import comb as c
from collections import defaultdict
input=stdin.readline

for _ in range(int(input())):
    n=int(input())
    s=input().rstrip()
    bef=''
    cnt=0
    for i in range(1,n):
        now=s[i]+s[i-1]
        if set(now)!=set(bef):
            cnt+=1
        bef=now
    print(cnt)

 

 

E번 풀이

문제

https://codeforces.com/contest/1800/problem/E1

 

Problem - E1 - Codeforces

 

codeforces.com

https://codeforces.com/contest/1800/problem/E2

 

Problem - E2 - Codeforces

 

codeforces.com

알고리즘 분류 

DFS, 구성적

 

풀이

문자 하나를 노드로 생각하고 그 문자와 거리가 k, k+1인 노드들이 연결되어 있다고 생각하고 풀면 될 거라 생각했다. 이 연결된 노드들을 구성하는 문자들이 순서와는 상관없이 동일하지 않다면 불가능하다고 생각했다.

그런데 왜인지 계속 런타임 에러가 발생해서 굉장히 고생을 했다.

 

그래서 생각을 뒤집어 보았다. 구성하는 문자열이 될 수 없는 문자열들이 있다. 예를 들어 해당 위치가 idx-k<0 그리고 idx+k<=n 인 경우 움직일 수 없는 곳이다. 해당 위치의 문자열이 아니라면 결국 하나의 문자열로 묶이게 되어있다.

따라서 해당 위치의 s[idx]와 t[idx]가 다르다면 NO 모두 같다면 YES를 출력해주면 된다.

 

from sys import stdin
input=stdin.readline

def solve():              
    n,k=map(int,input().split())
    s=input().rstrip()
    t=input().rstrip()
    if sorted(s)!=sorted(t):
        return 0
    able=True
    for i in range(n):
        if i-k<0 and i+k>=n:
            if s[i]!=t[i]:
                return 0
    return 1

for _ in range(int(input())):
    print("YES" if solve() else "NO")