[24.02.20] CF Round 927 div. 3 virtual + Gold 한 문제 풀기

2024. 2. 20. 14:40·PS 기록/내실 쌓기

 

A번은 가시가 두 번 나오기 전까지 coin 개수를 더해주면 된다.

import sys
input = sys.stdin.readline
 
T = int(input())
 
for _ in range(T):
    N = int(input())
    st = input().rstrip()
    cnt, flg = 0, 1
 
    for i in range(N-1):
        if st[i] == '@':
            cnt += 1
        if st[i] == '*' and st[i+1] == '*':
            flg = 0
            break
 
    print(cnt+1 if flg and st[-1] == '@' else cnt)

 

B번은 뇌 덜 깸 이슈로 문제 이해하는데 시간이 좀 걸렸다. 나는 처음에 어떤 기준으로 K th 기다림이 성립하는지 이해를 못해서 이것 저것 많이 해봤는데, arr 안에서 arr[0] ~ arr 끝까지 갈 때 무조건 한 번은 arr[k]의 배수 형태로 기다려줘야 한다는 사실을 늦게 발견했다.

그래서 B번은 쉬울 줄 알고 나이브하게 짰는데 TLE 맞길래, 오 B번부터 이분 탐색을 쓰는 건가? 흥미롭군...... 이러면서 이분 탐색을 넣었다.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int T;

int upper_bound(int now, int target) {
    int left = 1;
    int right = now/target + 1; // 초기 범위 설정

    while (left < right) {
        int mid = left + (right - left)/2;
        if (mid * target <= now) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    return left;
}


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> T;

    for (int t = 0; t < T; t++) {
        int N;
        cin >> N;

        vector<int> arr(N);
        for (int i = 0; i < N; i++) {
            cin >> arr[i];
        }

        int now = arr[0];

        for (int i = 1; i < N; i++) {
            if (now >= arr[i]) {
                int cnt = upper_bound(now, arr[i]);
                now = cnt * arr[i];
            } else {
                now = arr[i];
            }
        }
        cout << now << "\n";
    }

    return 0;
}

 

C번은 재밌는 문제였다. 모듈로 연산의 특징을 잘 이용하면 된다. 그런데 문제에서 하라는 대로 Left와 Right를 순서대로 빼서 연산하려고 하면 귀찮아진다. 모듈로 나눗셈을 해야하기 때문이다.

그래서 나는 생각의 전환을 해봤다. 문제에서는 L/R 명령을 기준으로 deque에서 앞/뒤로 빼는 순서를 정해주는데,  이 순서를 그대로 빼서 stack에 저장했다. 이렇게 되면 elements 가 기존 명령 순서와 반대로 스택에 쌓인다. 그 후에 스택에서 값을 하나씩 빼주면서 모듈로 곱셈을 해주고, 각 step 마다의 곱셈 결과를 result list에 저장해주면 된다.

마지막에는 list 순서를 reverse 해서 출력하면 쉽게 답을 구할 수 있다.

import sys
input = sys.stdin.readline

T = int(input())

from collections import deque

for _ in range(T):
    N, M = map(int, input().split())
    arr = list(map(int, input().split()))
    st = list(input().rstrip())

    now = 1
    new = deque()
    for i in range(N):
        new.append(arr[i]%M)
    order = []

    for i in range(N):
        if st[i] == 'L':
            order.append(new.popleft())
        else:
            order.append(new.pop())

    res_arr = []
    res = order.pop() #last element of order stack
    res_arr.append(res)

    for i in range(len(order)):
        tmp = order.pop()
        res = (res*tmp)%M
        res_arr.append(res)

    res_arr.reverse()
    print(*res_arr)

 

D번은... 처음에 게임이라고 하길래 게임 이론 문제인가 싶었다. 난 왜 게임 이론이 무섭지..? 주변에 게임 이론 문제를 좋아하셔서 한동안 이거 태그 달린 문제만 푸시는 분이 있었는데 진심으로 존경한다... (난 아직도 매 회차마다 본인이 이길 수 있는 최선의 선택을 하는게 뭔지 감이 잘 안온다. 공부 할 내용에 추가해야겠다.) 

아무튼 앞 내용은 그냥 헛소리였고 이 문제는 게임 이론과 상관 없는 문제다... 차근차근 다시 읽어 보면 조건 대로 맞춰서 구현해주면 된다. 대신 구현이 조금 시간이 걸려서 이쁘고 깔끔하게 구현하는게 중요하다.

 

E번은 각 자릿수가 바뀔 때마다 1초 추가를 해주면 된다. 대신 한 번에 여러 자리 수가 바뀌게 되면 그것도 다 추가해줘야 해서 약간 성가신 구현이 된다. reverse 해서 카운트 해줬다.

import sys
input = sys.stdin.readline

T = int(input())
for _ in range(T):
    N = int(input())
    s = input().rstrip()
    s = s[::-1]

    cnt = [0]*(N+1)
    now = 0

    for num in s:
        now += int(num)

    for i in range(N):
        cnt[i+1] = now
        now -= int(s[i])

    res = []
    for i in range(1, N):
        tmp = cnt[i] % 10
        cnt[i+1] += cnt[i] // 10
        res.append(tmp)

    res.append(cnt[N])
    res = res[::-1] #reverse
    flg = 1
    
    for num in res:
        if flg and num == 0:
            continue
        if num != 0:
            flg = 0
        print(num, end="")
    print()

 


 

아침에 일어나서 간단하게 밥먹고 8시 쯤에 버추얼을 돌렸다. 원래 목표는 가볍게 4솔 하고 끝내는거 였는데 B에서 시간을 너무 오래 써버렸다.

전에는 잘 안 와닿았는데 standings를 유심히 보다보니 스피드가 굉장히 중요한 것 같다. 물론 덜 틀려서 패널티 관리하는 것도 중요하지만, 대체적으로 같은 solve 안에서 시간 차로 퍼포가 엄청 갈리기 때문에 쉬운 문제를 빨리 처리하는게 중요하다고 느껴졌다. 물론 쉬운 문제를 빨리 푸는 건 연습 밖에 답이 없다.

나는 대체적으로 풀이를 완성하지 않고 일단 시작하는 편인데, 코드 작성 중에 생각을 수정하면 그대로 시간 소모를 하게 된다. 그래서 쉬운 문제는 풀이를 완결해놓고 들어가는 게 좋을 것 같다. 물론 A번은 그냥 냅다 짜도 잘 맞기 때문에 지금까지 신경 써 본적이 없는데 B번부터는 완결하는 연습을 해야겠다.

 


 

오늘 골드 문제는 문자열 관련 문제로 풀어봐야겠다. 어제 배웠던 라빈 카프를 구현해보고 관련 문제를 볼 생각이다... << 풀려고 했는데 chorus 문제가 단순 라빈 카프 적용하는거 뿐만 아니라 후렴구 처리를 한 번 더 해줘야 했다. 후렴구는 반복되는 문자열 중에 가장 긴 부분 문자열이라던데, 이걸 구하는 문제가 또 따로 있어서 이전 step의 문제를 먼저 보고 chorus를 풀 생각이다.

대신에 dp 문제를 하나 풀었다.

https://www.acmicpc.net/problem/1915

 

1915번: 가장 큰 정사각형

첫째 줄에 n, m(1 ≤ n, m ≤ 1,000)이 주어진다. 다음 n개의 줄에는 m개의 숫자로 배열이 주어진다.

www.acmicpc.net

 

2차원 격자가 주어져있어서 누가봐도 2차원 dp라는 느낌이 났다. 특히, 이런 문제는 본인을 정사각형의 우측 하단 꼭짓점으로 생각하는 경우가 많아서 그걸 첫 접근으로 시도했다.

우선 한 변이 2인 정사각형은 본인 위치 (i, j) 를 포함한 주변 (i-1, j-1) (i, j-1) (i-1, j)이 모두 1일 때 가능하다. 그러면 이걸 sub-problem 이라고 생각했을 때, 이 정보를 어떻게 저장해서 넘기면 다음 계산을 편하게 만들 수 있을까? 이런 방식으로 생각했다.

정사각형을 여러 모양으로 생각해보다가, 우측 하단 꼭짓점에 현재까지 가능한 변의 길이를 업데이트 하면,  (i, j) (i-1, j-1) (i, j-1) (i-1, j) 이렇게 네 값만 봐도 편하게 알 수 있다는 것을 발견했다.

네 개 중에 단 하나만 0이면 정사각형이 성립하지 않고, 나머지 길이가 다 2로 저장되어 있는데 하나만 1이어도 다음 크기의 정사각형을 만들 수 없었다. 그래서 본인이 만약에 0이 아닌 값을 들고 있다면 (i, j) 4개 칸의 min 값을 봐주고, min + 1 하면 된다.

import sys
input = sys.stdin.readline

N, M = map(int, input().split())
arr = []
for _ in range(N):
    li = list(input().rstrip())
    arr.append(li)

dp = [[0]*M for _ in range(N)]

# 자기 대각선 위 dp[i-1][j-1] 이 정사각형이고,
# 자기까지의 각 row, column이 1이면 ok
# 뭔가 dp[i][j]를 정사각형의 아래 꼭짓점으로 두고 check할 방법?

for i in range(N):
    for j in range(M):
        if arr[i][j] == '1':
            dp[i][j] = 1

for i in range(N):
    for j in range(M):
        if i == 0 or j == 0:
            continue
        if min(dp[i][j], dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) != 0:
            dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1])+1

res = 0
for i in range(N):
    for j in range(M):
        res = max(res, dp[i][j])
print(res**2)

 

저작자표시 비영리 변경금지

'PS 기록 > 내실 쌓기' 카테고리의 다른 글

[24.02.21] CF Round 922 div. 2 upsolve +  (0) 2024.02.21
회고  (0) 2024.02.19
'PS 기록/내실 쌓기' 카테고리의 다른 글
  • [24.02.21] CF Round 922 div. 2 upsolve +
  • 회고
pearl.k
pearl.k
이화여대 공대, PS, 개발
  • pearl.k
    Pearl
    pearl.k
  • 전체
    오늘
    어제
    • 분류 전체보기 (53)
      • Java Spring (10)
      • Android (1)
      • Kotlin (7)
      • Coroutines (2)
      • PS 기록 (20)
        • CP (6)
        • Algorithm (6)
        • 내실 쌓기 (3)
      • CS (0)
      • IT - 취업 DB (5)
      • SSAFY (2)
        • Algorithm (1)
      • Daily (3)
      • Books (2)
      • 기타 부트캠프 기록 (0)
        • 네이버 부스트캠프 (0)
        • 우아한테크코스 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
    • soundlcloud
  • 공지사항

  • 인기 글

  • 태그

    싸피 서울캠
    앳코더309
    solved.ac
    sw마에스트로 코테
    다익스트라
    앳코더후기
    백준 13334
    백준 2423
    코딩테스트
    싸피 12기
    http stream
    Grand Arena Party div2
    첫앳코더
    java
    웹모바일과정
    액티비티컴포넌트
    싸피 면접 후기
    자바@
    채용의나라
    백준
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
pearl.k
[24.02.20] CF Round 927 div. 3 virtual + Gold 한 문제 풀기
상단으로

티스토리툴바