<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>junhyung9985의 컴공 블로그</title>
    <link>https://jun9985.tistory.com/</link>
    <description>PS / Algorithm / 일상</description>
    <language>ko</language>
    <pubDate>Tue, 16 Jun 2026 14:32:07 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>junhyung9985</managingEditor>
    <item>
      <title>내가 출제했던 문제 리뷰</title>
      <link>https://jun9985.tistory.com/106</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;어제 백준이 섭종을 했답니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 추억을 남기려는 차원에서 이렇게 뒷 에디토리얼을 적어보려 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 총 4 문제를 출제 했었는데 모두 2023년에 진행한 제 2회 보라매컵 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 문제 별로 오프 더 레코드를 이야기해보려 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 29695번 기지방호 (G1)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 문제는 예선을 위해 Subtask가 존재하는 문제를 구상하다가 갑자기 떠올랐습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Floyd-Warshall DP를 약간만 비틀면 저렇게 문제를 낼 수 있겠더라구요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저거 출제하려고 할 때 개최하신 분께서 &quot;그래프라 TC 촘촘하게 만들기 많이 빡셀거다&quot; 이랬어서 TC를 엄청 열심히 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 본 대회 진행할 때, 실제로 테케가 도중에 뚫렸었고... 그걸 무마하려 중간에 PC방 가서 해결했던게 기억납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행이 본 대회가 2~3일 걸쳐 진행되는 대회였기에 오픈 대회 전에 어떻게 막는 TC들 넣을 수 있었네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 문제이고 수식도 깔끔해서 애착이 가지만, 중간 사고 때문에 약간 아쉬운 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 저 정도면 나름 잘 만든게 아닌가... 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 30205 전역 임무 (S2)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 읽어보면 알겠지만 문제 모티브는 그 유튜브 광고에서 나오던 Heros War 게임 맞습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억상으론 그때 스트리머 중 한 명이 유튜브에서 저 게임을 실제로 구현한 &quot;어디서 많이 본 그 게임을 막대 인간으로 진짜 만들어 봤는데, 과연 당신이 클리어할 수 있을까?&quot; 를 플레이 하는 걸 보았는데, 하도 많이 죽어서 떠오른 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당시에 많이 죽어서 저게 최적해가 뭘까 고민했는데 곱하기 아이템만 존재한다면 1. 몬스터들 최대한 잡고 2. 아이템 먹는게 최적이라는 아이디어가 떠올랐습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제화해도 괜찮을 것 같아 비슷한 문제 없는지 확인해보고 출제했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 입력 제한을 위한 Validator 구성이 좀 힘들었던게 기억납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 30206 차량 배치 (G4)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 구상하던 문제는 비슷하게 차량 배치했다가 충돌하는 아이디어는 있었긴 한데, 뭔가 LCA를 염두해두고 생각한 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다가 거리가 같으면 어차피 1번 노드에서 만나니 BFS로도 충분하여 다른 아이디어를 생각하고 있었는데, 어쩌다보니 조합론으로 문제를 틀어 출제하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구상한 문제 중에서 제일 빠르게 아이디어가 나왔던 문제 중 하나였던 걸로 기억납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면서도 조합론 + BFS 인 희귀한 조합에 문제 아이디어도 마음에 들어 애착가는 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(4문제 밖에 안 되지만, 그 중에서 제일 평이 좋았던 문제였던 것 같네요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 30210 BX 내기 (P3)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제의 의도는 약간 순수하진 않은데, 절 블루로 보내줬던 XOR Trie 알고리즘을 활용하는 문제 내보고 싶어서 구상한 아이디어 였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 블루 갈 수 있나 싶었는데, 덕분에 가서 언제 문제로 한 번 내보고 싶었거든요. 그래서 2진수 문제를 10진수로 확장해서 냈던 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 대회 특성상 XOR Trie가 덜한 웰노운이라 반대될 뻔 했지만, 이분 탐색 별해가 가능하여 Trie 선수 지식이 없어도 풀 수는 있어 출제되었습니다. (애초에 XOR Trie 문제가 set 이분탐색으로도 풀리는 거 생각보다 모를 것 같네요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여튼 이렇게 문제 회고를 간략하게 해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 백준을 제가 제대로 시작한 건 군 입대 이후였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이후로 꾸준히 했다가, 취업하고 나서는 한 동안 못 했었는데... 안타깝네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 submit은 &quot;악마의 유혹&quot;이었습니다. 어차피 섭종하는 데 뭐... 그래도 군생활을 책임져 준 사이트가 날라가는 건 많이 아쉽네요.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/기타</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/106</guid>
      <comments>https://jun9985.tistory.com/106#entry106comment</comments>
      <pubDate>Wed, 29 Apr 2026 22:50:19 +0900</pubDate>
    </item>
    <item>
      <title>Small To Large 내가 이해한 대로 설명하기</title>
      <link>https://jun9985.tistory.com/105</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 글을 올려봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;DSU 알고리즘에서 크기를 기준으로 union을 하면 O(NlogN)이 된다.&quot; 이게 Small-to-Large technique으로 전 알고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 이게 왜 O(NlogN)인가는 좀 직관적으로 이해가 잘 안 갔었는데... 최근에 인사이트가 생겨 이를 공유해보고자 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자... DSU 알고리즘에서 모든 element를 Union을 할 때 생기는 시간복잡도는 &quot;모든 element가 이동한 횟수&quot;가 될 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 각 element가 몇 번 정도 움직이는 지 파악하면 되겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 각 element가 언제까지 움직여야 할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 비틀어서 생각해보면 현재 element가 속한 집합의 크기가 N이 될 때 까지가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 element a가 속한 집합의 크기가 sz[a]라고 합시다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 집합의 크기가 sz[b]인 집합과 union해야 하는 상황이라고 보죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약에 sz[a] &amp;gt; sz[b]라면 sz[a] := sz[a]+sz[b]가 되긴 합니다. 다만, element a는 움직이지 않죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 sz[a] &amp;lt; sz[b]라면 sz[b] := sz[a]+sz[b]가 되고 element a는 움직이게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 element a가 속한 집합은 크기가 sz[a]에서 sz[a] + sz[b] &amp;gt; 2 * sz[a]가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적어도 element a 가 속한 집합의 크기가 2배 이상이 되는 경우에 element a가 움직이게 되는거죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 element a는 최대 몇 번을 움직이는 걸까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번 움직일 때 적어도 element a가 속한 집합의 크기 sz[a]는 sz[a] * 2 이상이 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 총 움직이는 횟수는 대략... sz[a] * 2 ^ (움직인 횟수)&amp;nbsp; = N 이므로 움직인 횟수 &amp;gt; logN 정도 되겠네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서&amp;nbsp; 각 element는 O(logN) 정도 움직이게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 총 element가 움직인 횟수는 O(NlogN)이 되겠죠.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Small-to-Large Technique이 O(NlogN)이 되는 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누군가에겐 이게 매우 당연할 수 있긴 할텐데...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 이걸 처음 본 걸 기준으로 대략 2년 정도 지나서야 직관적으로 이해되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이걸 제가 이해한 대로 나름 풀어서 공유해보고자 적었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글이 도움되셨다면 좋겠습니다!&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/기타</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/105</guid>
      <comments>https://jun9985.tistory.com/105#entry105comment</comments>
      <pubDate>Wed, 12 Nov 2025 00:15:07 +0900</pubDate>
    </item>
    <item>
      <title>2024 한양대학교 ERICA X 코드트리 전국 SW 프로그래밍 경진대회</title>
      <link>https://jun9985.tistory.com/104</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;지난번 구름edu에서 진행된 대회 이후에 또 다른 대회에 참여하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 대회는 한동대 / 우송대 / 한밭대 이렇게 세 대학교끼리 주최하여 진행한 것 같은데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 대회는 전국 대학교에서 참여하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대회 진행&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 마스코트 선별 시험 [실버 2]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열에서 K개의 element를 골랐을 때 element 간의 차이 중에서 최소 차이를 묻는 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬해서 a[i]와 a[i+K-1]의 차이를 구하여 그 중 최솟값을 구하면 되는 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬 + 그리디 유형으로 백준에서도 실버 2 정도 받았을 것 같네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도 : O(NlogN)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 개구리 점프 [골드 2]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1937&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1937&lt;/a&gt; 이 문제가 생각나는 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1,1), (1,2) ,... (N,M-1), (N,M) 순서대로 DP 테이블을 갱신하는 데, 각 테이블 값은 해당 좌표까지 가는 데에 최대 시간을 저장할 겁니다. (최단거리면 다익스트라로 풀 수 있어요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 도중에 스킬을 사용하는 경우도 있는데, 이를 위해서 또 (N,M)에서 (i,j)까지의 최대 거리를 계산을 해주어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 (i,j) 이하의 좌표들 중에서 (N,M)까지의 최대 거리를 바로 구할 수 있도록 또 업데이트를 해주어야죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에는 각 칸에 대해서 DP 테이블 값과 해당 칸에서 스킬을 사용했을 때의 최대 거리를 더하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준에서는 골드 2~1 사이가 적당할 것 같은 문제였어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도 : O(NM(N+M))&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 최댓값 갱신 함수의 반환값 [플레티넘 4]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수는 대강 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1732957013952&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Python style pseudo-code

def func(a,b,c):
    cnt = 0
    maxx = 0
    for i in range(a, b+1):
        if(A[i] &amp;gt; maxx) :
            maxx = A[i]
            cnt += 1
    if(cnt == c) : return maxx
    return -1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 잘 생각해보면, &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;index값 i에서 다음으로 갱신될 index j는 항상 정해져 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;그리고 index j에서 다음으로 갱신될 index도 마찬가지 일 것이고요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이를 트리 구조처럼 생각을 해봅시다. 즉, p[i] = j 라면 A[i] 이후에 갱신될 다음 값은 A[j]이다 이렇게 표현해보죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;그러면 c번 갱신한 결과 == p[i]에서 c-1번째 위의 parent의 값이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이는 또 Sparse table을 활용한다면 O(logN) 만에 구할 수가 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;트리 구조는 priority queue나 set으로 O(NlogN)만에 구현할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;(전에 매칭이 안 된 index들을 pop하면서 parent 배열을 채워주면 되므로)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;그리고 sparse table을 세우는 데도 O(NlogN), 이후 각 쿼리별로 대답해주는 건 O(QlogN)만에 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Time complexity : O((N+Q)logN)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;4. 제 점수는요 [플레티넘 2]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리 두 가지를 처리해야 하는 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;쿼리&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. update(idx, val) : idx 위치의 값을 val로 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. query(idx) : [idx-R, idx+R] 사이의 값들 중 idx위치의 값과 동일한 값의 개수를 구한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번 쿼리만 있다면 Mo's나 Merge sort tree로 풀 수 있었는데, 1번 쿼리가 들어옴에 생각을 좀 바꿨어야 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Merge sort tree에 PBDS를 같이 박는 생각도 해보아 직접 구현했는데, 시간초과과 났고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 Memory 문제는 있을 수도 있겠지만, PBDS가 다이나믹으로 할당해주는 세그일 것이라 믿고 PBDS를 100'000개를 만들어 이를 해결하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정해는 Sqrt-decomposition이었다고 하네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Time complexity : 제 풀이는 O((N+Q)logN)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결과 및 후기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 아직 안 나왔는데, 너무 잘하는 사람들이 많아 상은 하나도 못 탈 예감은 듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 문제들의 난이도가 상당했고 티어 분류도 백준이랑 유사해서 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;매우&lt;/span&gt; 놀랐습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매우 재밌고 도전되는 문제들이었습니다.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/대회 후기</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/104</guid>
      <comments>https://jun9985.tistory.com/104#entry104comment</comments>
      <pubDate>Sat, 30 Nov 2024 18:10:22 +0900</pubDate>
    </item>
    <item>
      <title>2024 전국 대학생 프로그래밍 경진대회 후기</title>
      <link>https://jun9985.tistory.com/103</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;11월 16일에 전국 대학생 프로그래밍 경진대회가 있다길래 참여해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음주 ICPC 본선 전에 몸도 풀겸 참여해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험 환경은 비대면으로 시험을 치는 지라, Softeer에서의 HSAT과 같이 웹캠 등을 켜서 진행했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;사전 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사전에 테스트를 쳐야하기에, 한 번 쳐보았습니다. 4문제에 6시간 정도 주어지는데 총 40분 정도 걸렸던 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사전에 풀었던 문제는 다음과 같았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. UXUI 디자이너&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;문제 : &lt;a href=&quot;https://level.goorm.io/exam/163020/uxui-%EB%94%94%EC%9E%90%EC%9D%B4%EB%84%88/quiz/1&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://level.goorm.io/exam/163020/uxui-%EB%94%94%EC%9E%90%EC%9D%B4%EB%84%88/quiz/1&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1731643721718&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;구름LEVEL&quot; data-og-description=&quot;난이도별 다양한 문제를 해결함으로써 SW 역량을 향상시킬 수 있습니다.&quot; data-og-host=&quot;level.goorm.io&quot; data-og-source-url=&quot;https://level.goorm.io/exam/163020/uxui-%EB%94%94%EC%9E%90%EC%9D%B4%EB%84%88/quiz/1&quot; data-og-url=&quot;https://level.goorm.io&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bIoq92/hyXwp9Dul8/XCaPasC4GogCrRfbmqoZ0k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://level.goorm.io/exam/163020/uxui-%EB%94%94%EC%9E%90%EC%9D%B4%EB%84%88/quiz/1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://level.goorm.io/exam/163020/uxui-%EB%94%94%EC%9E%90%EC%9D%B4%EB%84%88/quiz/1&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bIoq92/hyXwp9Dul8/XCaPasC4GogCrRfbmqoZ0k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;구름LEVEL&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;난이도별 다양한 문제를 해결함으로써 SW 역량을 향상시킬 수 있습니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;level.goorm.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 - 참여 횟수를 저장할 수 있는 array 하나 만들면 되는 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면, 이벤트 중에서 최대 참여 횟수와 동일한 이벤트들만 출력하면 되니 말이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬해도 되고, 안 해도 되는 문제입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도 : O(NlogN+M) or O(N+M).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 이상한 미로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 : &lt;a href=&quot;https://level.goorm.io/exam/163023/%EC%9D%B4%EC%83%81%ED%95%9C-%EB%AF%B8%EB%A1%9C/quiz/1&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://level.goorm.io/exam/163023/%EC%9D%B4%EC%83%81%ED%95%9C-%EB%AF%B8%EB%A1%9C/quiz/1&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1731643900814&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;구름LEVEL&quot; data-og-description=&quot;난이도별 다양한 문제를 해결함으로써 SW 역량을 향상시킬 수 있습니다.&quot; data-og-host=&quot;level.goorm.io&quot; data-og-source-url=&quot;https://level.goorm.io/exam/163023/%EC%9D%B4%EC%83%81%ED%95%9C-%EB%AF%B8%EB%A1%9C/quiz/1&quot; data-og-url=&quot;https://level.goorm.io&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/YoQet/hyXwivEwVt/hlyKRixoKrU4vk1k8K8RH0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://level.goorm.io/exam/163023/%EC%9D%B4%EC%83%81%ED%95%9C-%EB%AF%B8%EB%A1%9C/quiz/1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://level.goorm.io/exam/163023/%EC%9D%B4%EC%83%81%ED%95%9C-%EB%AF%B8%EB%A1%9C/quiz/1&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/YoQet/hyXwivEwVt/hlyKRixoKrU4vk1k8K8RH0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;구름LEVEL&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;난이도별 다양한 문제를 해결함으로써 SW 역량을 향상시킬 수 있습니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;level.goorm.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다익스트라 응용 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A[i]의 값 범위가 1~10 이라면, 항상 나머지의 범위는 0~9 사이입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 활용해 거리를 저장하는 array를 dist[left_over][node_number] 이런식으로 저장할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PQ에는 해당 노드로 들어오기 전의 노드의 정보를 저장하여 다음으로 향할 노드들 중 어떤 노드만 가능한 지를 파악할 수 있게 해야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도는 O(10*(V+E)logV).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3,4 번은 실제 문제가 없어서 대충 유형만 말하자면...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번 : Hash map/set을 안다면 쉽게 풀 수 있는 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4번 : 2차원 누적 합 구현 + 이분 탐색을 요구하는 문제였습니다. 총 시간복잡도는 O(N^2logN).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이렇게 모의 테스트도 시간내로 잘 풀었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;본 대회 날&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음날은 본 대회가 있는 날이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 총 3시간인 줄 알았는데... 14~16시 총 2시간에 4문제였더라구요...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 한 번 풀어보긴 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 아직 안 올라온 것 같아 대강 풀이만 설명하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 깡 구현 + 수학 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리 어렵지 않은 구현 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자 나눈 나머지 가지고 노는 문제였는데 높게 쳐줘도 B3?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 깡 BFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 기본 문제로, 2차원 지도에서 특정 점으로부터 다른 점까지의 최단거리 구하는 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준에서는 한 실버 2~1 정도 주긴 할 것 같네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 정렬 + 이분탐색 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대강 배열 내에서 두 원소를 골랐을 때 원소 차이가 K 이하인 경우의 수 구하기인데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N 범위가 너무 커서 O(N^2)를 막아두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열을 정렬하면, a[i]과 차이가 K 이하인 a[j] ( j &amp;gt; i )가 가능한 제일 멀리 떨어져 있는 index라면 a[j-1], a[j-2], ..., a[i+1] 도 가능하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이분탐색을 활용하면 O(NlogN) 만에 구할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준에서는 한 골3~2 정도 될 것 같아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. DP + 최적화???&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 상황 : 숫자 N개 중에서 K개를 골라서 곱셈, K개를 골라 곱셈한 수를 10으로 나눌 수 있는 횟수 만큼 점수가 됨, 최대 점수?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이 문제는 결국 곱셈을 했을 때에 10^k = (2^k *&amp;nbsp; 5^k)의 배수가 되는지가 중요하므로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 수를 {2 로 나눌 수 있는 횟수 , 5로 나눌 수 있는 횟수} 이렇게 관리하는 건 맞는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이후에 어떻게 풀어야 할 지 감이 잘 안 왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직도 이 문제의 정해는 잘 모르겠지만... (N &amp;gt;= 100이라 bitset DP는 아닌 것 같았음.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해가 될 수 있는 경우의 수를 계속 줄여나갈 수 있었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;dp[t]는 set으로 t개의 element로 만들 수 있는 점수가 제일 높거나 더 높아질 수 있는 해들의 후보를 저장할 겁니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;i번째 element를 보고 있는 도중에 dp[t]를 갱신한다면, dp[t-1]에서 가능한 후보를 하나씩 꺼내고 거기에 i를 곱한 결과를 dp[t]에 넣을 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;dp[t]에서 절대로 해가 될 수 없는 후보들은 다음과 같습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;dp[t]에서 {a1, a2}와 {b1, b2} 가 있을 때 a1 &amp;gt; b1, a2 &amp;gt; b2 라면 {b1,b2}는 절대로 해가 될 수 없습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;왜냐하면 i(i &amp;gt; 0)값을 {i1, i2}로 표현하고 각각 a와 b에 곱한다고 생각합시다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러면 a * i 와 b * i를 각각 10으로 나눌 수 있는 횟수는 min(a1+i1, a2+i2)&amp;nbsp; &amp;gt; min(b1+i1, b2+i2) 이런 관계를 가지기 때문에 b는 해가 될 수 없습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이런 경우들을 지속적으로 확인하여 해의 후보에서 없애주니 맞았습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저도 시간복잡도 증명까진 못해서 좀 아쉬웠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;387&quot; data-origin-height=&quot;332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cm0xNt/btsK1Qy0chj/f25HuF6mpsGK5a2Scl4Ow0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cm0xNt/btsK1Qy0chj/f25HuF6mpsGK5a2Scl4Ow0/img.png&quot; data-alt=&quot;결과 : 올솔브 / 1~4번 문제 다 푸는 데 1시간 19분&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cm0xNt/btsK1Qy0chj/f25HuF6mpsGK5a2Scl4Ow0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcm0xNt%2FbtsK1Qy0chj%2Ff25HuF6mpsGK5a2Scl4Ow0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;387&quot; height=&quot;332&quot; data-origin-width=&quot;387&quot; data-origin-height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;결과 : 올솔브 / 1~4번 문제 다 푸는 데 1시간 19분&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;결과&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-11-19 151552 - 복사본.png&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5tW7k/btsK33JTj1S/j3DwDKKltbVeXuV2gko1X0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5tW7k/btsK33JTj1S/j3DwDKKltbVeXuV2gko1X0/img.png&quot; data-alt=&quot;끼얏호우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5tW7k/btsK33JTj1S/j3DwDKKltbVeXuV2gko1X0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5tW7k%2FbtsK33JTj1S%2Fj3DwDKKltbVeXuV2gko1X0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1039&quot; height=&quot;176&quot; data-filename=&quot;스크린샷 2024-11-19 151552 - 복사본.png&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;176&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;끼얏호우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;만점자가 저 혼자였기에 대회에서 1등 하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;막학기에 이런 대회도 1등 하니 기분이 좋네요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;대회 문제들은 체감상 마지막 문제 제외하고는 매우 typical 한 문제들만 나왔다고 생각합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 이유는 문제 풀이 속도가 이를 어느정도 증명한다고 생각합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(문제를 보자마자 아이디어와 시간복잡도 계산이 바로 되긴 했어요.)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다만, 4번째 문제는 정해가 뭔지 엄청 궁금합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/대회 후기</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/103</guid>
      <comments>https://jun9985.tistory.com/103#entry103comment</comments>
      <pubDate>Sat, 30 Nov 2024 17:37:28 +0900</pubDate>
    </item>
    <item>
      <title>2024 ICPC Seoul Regional First Round 후기</title>
      <link>https://jun9985.tistory.com/102</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이번에 KimsaiAn 팀명으로 ICPC에 참여해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희 팀은 E,F,H 이렇게 총 3 문제를 풀었는데, 어떻게 풀었는지 풀어본 순서대로 복기해보려 합니다. &lt;br /&gt;&lt;br /&gt;E&amp;nbsp;:&amp;nbsp;행렬&amp;nbsp;게임 &lt;br /&gt;처음에&amp;nbsp;어떤&amp;nbsp;문제가&amp;nbsp;쉬울지&amp;nbsp;감이&amp;nbsp;안&amp;nbsp;오다가&amp;nbsp;스코어보드에서&amp;nbsp;E번을&amp;nbsp;다들&amp;nbsp;풀기에&amp;nbsp;저희도&amp;nbsp;풀어보았습니다. &lt;br /&gt;서두르느라&amp;nbsp;수식이&amp;nbsp;안&amp;nbsp;보였지만,&amp;nbsp;a와&amp;nbsp;b&amp;nbsp;행렬의&amp;nbsp;값&amp;nbsp;차이의&amp;nbsp;절댓값은&amp;nbsp;칸&amp;nbsp;별로&amp;nbsp;미리&amp;nbsp;계산할&amp;nbsp;수&amp;nbsp;있어보였습니다. &lt;br /&gt;그러면,&amp;nbsp;각&amp;nbsp;열&amp;nbsp;별로&amp;nbsp;a와&amp;nbsp;b&amp;nbsp;행렬의&amp;nbsp;값&amp;nbsp;차이가&amp;nbsp;제일&amp;nbsp;큰&amp;nbsp;값들도&amp;nbsp;미리&amp;nbsp;찾을&amp;nbsp;수&amp;nbsp;있겠죠? &lt;br /&gt;&lt;br /&gt;미리&amp;nbsp;각&amp;nbsp;열&amp;nbsp;j&amp;nbsp;별로&amp;nbsp;|a[i][j]&amp;nbsp;-&amp;nbsp;b[i][j]|&amp;nbsp;가&amp;nbsp;제일&amp;nbsp;큰&amp;nbsp;i&amp;nbsp;위치들을&amp;nbsp;구하던지&amp;nbsp;아니면&amp;nbsp;|a[i][j]&amp;nbsp;-&amp;nbsp;b[i][j]|&amp;nbsp;값들을&amp;nbsp;저장해둡시다. &lt;br /&gt;그리고&amp;nbsp;M개에&amp;nbsp;대해서&amp;nbsp;미리&amp;nbsp;계산을&amp;nbsp;해둔&amp;nbsp;값들로&amp;nbsp;더해주면&amp;nbsp;됩니다. &lt;br /&gt;&lt;br /&gt;총&amp;nbsp;시간복잡도&amp;nbsp;:&amp;nbsp;O(N^2&amp;nbsp;+&amp;nbsp;M) &lt;br /&gt;&lt;br /&gt;H : 숫자 할당 (2 WA)&lt;br /&gt;이&amp;nbsp;문제는&amp;nbsp;13!&amp;nbsp;가지의&amp;nbsp;경우에&amp;nbsp;수가&amp;nbsp;있을&amp;nbsp;텐데&amp;nbsp;어떻게&amp;nbsp;0.1초&amp;nbsp;내로&amp;nbsp;풀어야&amp;nbsp;할&amp;nbsp;지&amp;nbsp;감이&amp;nbsp;안&amp;nbsp;왔습니다. &lt;br /&gt;13!&amp;nbsp;=&amp;nbsp;6,227,020,800&amp;nbsp;이니깐&amp;nbsp;적어도&amp;nbsp;1분은&amp;nbsp;걸릴&amp;nbsp;것이라고&amp;nbsp;예측되니&amp;nbsp;이에&amp;nbsp;따른&amp;nbsp;경우의&amp;nbsp;수를&amp;nbsp;줄여야&amp;nbsp;합니다. &lt;br /&gt;&lt;br /&gt;처음에는&amp;nbsp;13!&amp;nbsp;전부&amp;nbsp;계산&amp;nbsp;시켜보았습니다.&amp;nbsp;당연히&amp;nbsp;TLE가&amp;nbsp;나왔습니다. &lt;br /&gt;조금&amp;nbsp;경우의&amp;nbsp;수를&amp;nbsp;줄여보니,&amp;nbsp;a,b,c,e,f,g,i,j만&amp;nbsp;있으면&amp;nbsp;l,m,k,d,h&amp;nbsp;값은&amp;nbsp;A,B,C,D,E,F,G,H&amp;nbsp;값들을&amp;nbsp;통해서&amp;nbsp;정할&amp;nbsp;수&amp;nbsp;있음을&amp;nbsp;파악했습니다. &lt;br /&gt;그런데&amp;nbsp;이래도&amp;nbsp;13P8&amp;nbsp;=&amp;nbsp;51,891,840가지의&amp;nbsp;경우의&amp;nbsp;수가&amp;nbsp;생겨서&amp;nbsp;TLE를&amp;nbsp;받았습니다. &lt;br /&gt;&lt;br /&gt;좀&amp;nbsp;더&amp;nbsp;생각해보니,&amp;nbsp;a,b,c,e,f,i&amp;nbsp;6개를&amp;nbsp;미리&amp;nbsp;구하면&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;나머지&amp;nbsp;수들을&amp;nbsp;구할&amp;nbsp;수&amp;nbsp;있습니다. &lt;br /&gt;&lt;br /&gt;d&amp;nbsp;=&amp;nbsp;E&amp;nbsp;-&amp;nbsp;(a+b+c) &lt;br /&gt;l&amp;nbsp;=&amp;nbsp;A&amp;nbsp;-&amp;nbsp;(a+e+i) &lt;br /&gt;h&amp;nbsp;=&amp;nbsp;D&amp;nbsp;-&amp;nbsp;d &lt;br /&gt;m&amp;nbsp;=&amp;nbsp;H&amp;nbsp;-&amp;nbsp;l &lt;br /&gt;g&amp;nbsp;=&amp;nbsp;F&amp;nbsp;-&amp;nbsp;(e+f+h) &lt;br /&gt;j&amp;nbsp;=&amp;nbsp;B&amp;nbsp;-&amp;nbsp;(b+f+m) &lt;br /&gt;k&amp;nbsp;=&amp;nbsp;C&amp;nbsp;-&amp;nbsp;(c+g)&amp;nbsp;=&amp;nbsp;G&amp;nbsp;-&amp;nbsp;(i+j) &lt;br /&gt;&lt;br /&gt;그래서&amp;nbsp;13P6&amp;nbsp;=&amp;nbsp;1,235,520&amp;nbsp;가지의&amp;nbsp;경우의&amp;nbsp;수로&amp;nbsp;줄일&amp;nbsp;수&amp;nbsp;있었고&amp;nbsp;각&amp;nbsp;경우의&amp;nbsp;수&amp;nbsp;별로&amp;nbsp;d,l,h,m,g,j,k&amp;nbsp;들이&amp;nbsp;양수이며&amp;nbsp;서로&amp;nbsp;겹치는&amp;nbsp;값이&amp;nbsp;없는지&amp;nbsp;확인해주면&amp;nbsp;되었습니다. &lt;br /&gt;또한,&amp;nbsp;C&amp;nbsp;-&amp;nbsp;(c+g)&amp;nbsp;==&amp;nbsp;G&amp;nbsp;-&amp;nbsp;(i+j)&amp;nbsp;도&amp;nbsp;고려해주기도&amp;nbsp;했었습니다. &lt;br /&gt;아이디어도&amp;nbsp;아이디어지만,&amp;nbsp;구현도&amp;nbsp;상당히&amp;nbsp;귀찮았던&amp;nbsp;문제였습니다. &lt;br /&gt;&lt;br /&gt;총&amp;nbsp;시간복잡도&amp;nbsp;:&amp;nbsp;사실상&amp;nbsp;O(13^6)&amp;nbsp;//&amp;nbsp;중간에&amp;nbsp;continue&amp;nbsp;같은&amp;nbsp;걸로&amp;nbsp;커팅도&amp;nbsp;하긴&amp;nbsp;했지만,&amp;nbsp;매우&amp;nbsp;크게는&amp;nbsp;이렇게&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있을&amp;nbsp;것&amp;nbsp;같아요. &lt;br /&gt;&lt;br /&gt;F : 채굴권 분할 (5 WA)&lt;br /&gt;다음으로&amp;nbsp;많이들&amp;nbsp;푼&amp;nbsp;문제가&amp;nbsp;F번인데...&amp;nbsp;사실&amp;nbsp;기하&amp;nbsp;문제는&amp;nbsp;너무&amp;nbsp;싫어서&amp;nbsp;포기할&amp;nbsp;까&amp;nbsp;생각했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;중간에&amp;nbsp;수식을&amp;nbsp;잘못세운&amp;nbsp;경우들과&amp;nbsp;생각을&amp;nbsp;좀&amp;nbsp;잘못해서&amp;nbsp;여러번&amp;nbsp;틀렸는데,&amp;nbsp;저희&amp;nbsp;팀&amp;nbsp;최종&amp;nbsp;아이디어는&amp;nbsp;두&amp;nbsp;점을&amp;nbsp;가로지르는&amp;nbsp;직선의&amp;nbsp;개수가&amp;nbsp;짝수면&amp;nbsp;YES&amp;nbsp;아니면&amp;nbsp;NO를&amp;nbsp;출력하기로&amp;nbsp;하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이후에&amp;nbsp;직선&amp;nbsp;수식을&amp;nbsp;cos,&amp;nbsp;sin을&amp;nbsp;활용해서&amp;nbsp;세웠어야&amp;nbsp;했는데,&amp;nbsp;거기서&amp;nbsp;계속&amp;nbsp;틀렸었고...&amp;nbsp;직선&amp;nbsp;위에&amp;nbsp;있는지&amp;nbsp;아래&amp;nbsp;있는지&amp;nbsp;판단하는&amp;nbsp;기준도&amp;nbsp;잘못&amp;nbsp;짜서&amp;nbsp;틀렸고...&amp;nbsp;그러다가&amp;nbsp;맞았습니다. &lt;br /&gt;&lt;br /&gt;총&amp;nbsp;시간복잡도&amp;nbsp;:&amp;nbsp;O(N) &lt;br /&gt;&lt;br /&gt;총평&amp;nbsp;:&amp;nbsp;이번에&amp;nbsp;ICPC&amp;nbsp;예선&amp;nbsp;난이도는&amp;nbsp;작년에&amp;nbsp;비해&amp;nbsp;훨씬&amp;nbsp;어려웠던&amp;nbsp;것&amp;nbsp;같습니다.&amp;nbsp; &lt;br /&gt;A,&amp;nbsp;K번이&amp;nbsp;비교적&amp;nbsp;쉬웠다는&amp;nbsp;후기를&amp;nbsp;듣긴&amp;nbsp;했는데...&amp;nbsp;K번은&amp;nbsp;4장을&amp;nbsp;읽을&amp;nbsp;시간과&amp;nbsp;마음의&amp;nbsp;여유가&amp;nbsp;없었고,&amp;nbsp;A번은&amp;nbsp;거의&amp;nbsp;많이들&amp;nbsp;안&amp;nbsp;풀어서&amp;nbsp;읽을&amp;nbsp;여유가&amp;nbsp;없었습니다. &lt;br /&gt;좀 더 여유를 가지고 대회에 임했었으면 성적이 더 좋았을 것 같은데 아쉬움이 들면서도 재밌었습니다.&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/대회 후기</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/102</guid>
      <comments>https://jun9985.tistory.com/102#entry102comment</comments>
      <pubDate>Fri, 15 Nov 2024 13:04:56 +0900</pubDate>
    </item>
    <item>
      <title>Convex function의 특징 및 왜 Binary Cross Entropy는 convex 한가?</title>
      <link>https://jun9985.tistory.com/101</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 머신러닝 부트캠프에 합격해서 머신러닝 개념들을 다시 처음부터 공부하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 LR(Logistic Regression), BCE(Binary Cross Entropy) 등을 보기 시작하니 오랫만에 옛날 친구들을 만나는 심정으로 보고 있는데, loss function이 BCE일 때에 아래와 같은 그림이 나온다고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;473&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pHgtv/btsIjIIJy5X/HBVhpxuRV615YlvwWOCr21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pHgtv/btsIjIIJy5X/HBVhpxuRV615YlvwWOCr21/img.png&quot; data-alt=&quot;w, b에 대한 parameter에 대한 cost function의 값을 시각화 한 다이어그램. 보다시피 convex 하다!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pHgtv/btsIjIIJy5X/HBVhpxuRV615YlvwWOCr21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpHgtv%2FbtsIjIIJy5X%2FHBVhpxuRV615YlvwWOCr21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;773&quot; height=&quot;473&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;473&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;w, b에 대한 parameter에 대한 cost function의 값을 시각화 한 다이어그램. 보다시피 convex 하다!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 저는 어떻게 Binary Cross Entropy가 convex 한 성질을 가지고 있는가 궁금해졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 BCE를 사용한 cost function은 아래와 같이 정리가 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2094&quot; data-origin-height=&quot;1232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caLXDQ/btsIhLG7Aeq/xw8JzX8H2Vr6wxWZkMkw81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caLXDQ/btsIhLG7Aeq/xw8JzX8H2Vr6wxWZkMkw81/img.png&quot; data-alt=&quot;y=1 일 때 y_hat이 1 가까이, y = 0 일 때 y_hat이 0 가까운 값일 수록 누적되는 BCE가 작아집니다. 또한, cost function은 모든 BCE 값의 평균이 됩니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caLXDQ/btsIhLG7Aeq/xw8JzX8H2Vr6wxWZkMkw81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaLXDQ%2FbtsIhLG7Aeq%2Fxw8JzX8H2Vr6wxWZkMkw81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;488&quot; height=&quot;287&quot; data-origin-width=&quot;2094&quot; data-origin-height=&quot;1232&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;y=1 일 때 y_hat이 1 가까이, y = 0 일 때 y_hat이 0 가까운 값일 수록 누적되는 BCE가 작아집니다. 또한, cost function은 모든 BCE 값의 평균이 됩니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 log 값도 있고... y_hat = a(wx+b) 인데, a 는 심지어 sigmoid function 입니다. (그래서 MSE를 사용하면 non-convex 해진다고 하죠...) 그런데 어떻게 이 식이 convexity를 가질까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 convex function 에 대한 정의와 특성들을 살펴봅시다. convex function의 정의는 함수 위의 임의의 두 점을 잇는 직선을 그으면 내부의 점들이 모두 함수 보다 아래가 되어야 합니다. (그래서 convex function은 local optima가 없습니다. 항상 global optimum에 도달하죠.) 수식으로 멋지게 설명하자면...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;110&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XOsnO/btsIhvRVjtY/apt92zJ0pBdyh6vFhphi2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XOsnO/btsIhvRVjtY/apt92zJ0pBdyh6vFhphi2k/img.png&quot; data-alt=&quot;고마워요 ChatGPT!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XOsnO/btsIhvRVjtY/apt92zJ0pBdyh6vFhphi2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXOsnO%2FbtsIhvRVjtY%2Fapt92zJ0pBdyh6vFhphi2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;595&quot; height=&quot;110&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;110&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;고마워요 ChatGPT!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 식을 풀어서 설명하자면... lambda (편의를 위해 a라고 하겠습니다.) 값이 0 과 1 사이의 실수이므로 ax + (1-a)y는 x와 y 사이의 값들이 됩니다. 이를 z라고 쉽게 표현합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, f(x)와 f(y)를 잇는 직선은 일차식 형태를 띄므로 F(X) = wX+b, F(x) = f(x) and F(y) = f(y)가 됩니다. 그러면 F(z) = F(ax + (1-a) y) = w(ax + (1-a)y) + b = a wx +(1-a) wy + b = awx + ab + (1-a)wy + (1-a)b = aF(x) + (1-a)F(y) = af(x) + (1-a)f(y) 이렇게 식이 전개가 됩니다. 따라서 위의 식은 convex function의 정의와 동치입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 function이 convex한지(convexity)에 대한 증명은 크게 두 가지(이차 미분, Jenson의 부등식) 방법이 있지만 그 중에서도 이차 미분을 통한 증명만 알아볼 겁니다. (다만 이차 미분은 미분을 두 번 이상 가능한 함수만 적용할 수 있습니다.) 함수를 이차 미분을 한 f''(x) 는 함수 f의 곡률을 나타냅니다. 곡률이 양수이면 함수는 볼록한 형태를 가지는데, 이게 항상 양수 혹은 0이면 f는 어느 점에서도 볼록한 형태를 가지므로 convexity가 증명이 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 이제 BCE가 convexity를 가지고 있는지 이차 미분을 해서 알아봅시다. 우선 y가 0과 1일 때 계산할 값이 달라지므로 케이스를 나눠서 구해봅시다. 그리고 y_hat은 0과 1 사이의 실수값인 걸 잊지 맙시다. (Sigmoid function 이므로 y_hat은 절대 정확히 0 혹은 1이 될 수 없습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 y = 1 이라면 L(y_hat) = - log(y_hat) 이 됩니다. 이를 이차 미분 한다면...&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;L' (y_hat) = - 1 / (y_hat) = - (y_hat) ^ (-1)&lt;/li&gt;
&lt;li&gt;L'' (y_hat) = (y_hat)^(-2) = 1 / (y_hat)^2 이므로 항상 0 이상의 값을 가집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 y = 0 이라면... L(y_hat) = - log(1 - y_hat)일 것이고 이차 미분을 한다면...&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;L' (y_hat) = 1 / (1-y_hat) =&amp;nbsp; (1-y_hat) ^ (-1)&lt;/li&gt;
&lt;li&gt;L'' (y_hat) = (1-y_hat)^(-2) = 1 / (1-y_hat)^2 이므로 항상 0 이상의 값을 가집니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 모든 y의 경우에서 이차 미분한 결과는 항상 0 이상의 값을 가짐을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, BCE는 convex function입니다. 즉, 항상 최적의 해로 수렴하는 함수라는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 번외로 왜 MSE 는 non-convex 할까요? 이는 아래의 ChatGPT가 설명한 걸 노트로 남겨두겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA1BGg/btsIioLe4Zy/ufwKX1tnGucIhJ8cNUv7JK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA1BGg/btsIioLe4Zy/ufwKX1tnGucIhJ8cNUv7JK/img.png&quot; data-alt=&quot;고마워요! ChatGPT (2)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA1BGg/btsIioLe4Zy/ufwKX1tnGucIhJ8cNUv7JK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA1BGg%2FbtsIioLe4Zy%2FufwKX1tnGucIhJ8cNUv7JK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;670&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;고마워요! ChatGPT (2)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 설명에 추가로 노트를 남겨두자면 동일한 원리로 MLP 같이 중간 중간에 비선형적인 activation function들이 들어가면 MSE는 non-convex 해집니다. 반면에 BCE는 항상 convex 하죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 Convexity 증명과 왜 BCE 가 convex 한지를 정리해보았습니다. 예전에 ML 공부했을 때에는 convexity라는 뜻을 잘 몰라서 이를 간과하고 공부를 했었는데, 알고리즘 공부하면서 convex의 의미도 공부해보고 다시 돌아와보니 이해가 가능하더군요. 또한, MSE가 항상 convex 하지 않다는 건 이번에 처음 안 것 같습니다. 그와 별개로 ChatGPT 성능이 엄청 미친 것 같습니다. 엄청 도움되기도 하고 답변 속도도 엄청 빨라서 놀랐네요;;;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI &amp;amp; ML &amp;amp; DL/정리</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/101</guid>
      <comments>https://jun9985.tistory.com/101#entry101comment</comments>
      <pubDate>Mon, 1 Jul 2024 14:43:13 +0900</pubDate>
    </item>
    <item>
      <title>2024. 06. 19. ~ 2024. 06. 25.</title>
      <link>https://jun9985.tistory.com/100</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 7 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 14654 : 스테판 쿼리 - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation, Simulation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주어진 기록대로 시뮬레이션을 돌려서 푸는 문제였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐 같은걸로 시뮬레이션을 돌리는 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 15084 : Treating Fractions Irrationally - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation, Math, Arithmetic 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나눗셈을 실제로 구현해서 돌리면서 0,9가 먼저 나오는지 아니면 주기성이 먼저 나오는지를 확인하는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n &amp;lt; d이므로 n * 10 / d 이렇게 몫을 구하고 n = (n*10) % d 이렇게 나머지로 n을 다시 업데이트 해주면서 나눗셈을 구현한다. 그러면서 주기성은 n * 10 가 이미 존재한 적이 있는지를 파악하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주기 최대 길이가 d일 것이므로... (n은 %d 값을 취하니깐 n 값은 0 ~ d-1 사이의 값이 된다.) 시간복잡도는 O(d)일 듯.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 14731 : 謎紛芥索紀 (Large) - S1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Divide and Conquer, Math, Calculus 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할정복을 활용하여 2의 거듭제곱을 O(logK)만에 계산하고 결과값을 C * K 랑 같이 곱해서 더해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 시간복잡도는 O(NlogK).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 26091 : 현대모비스 소프트웨어 아카데미 - S1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 Multiset, Binary Search로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티셋의 lower_bound 메소드를 활용한다면 현재 남아있는 풀 중에서 제일 작은 값과 더했을 때에 M 이상이 되는 최솟값을 O(logN)만에 파악이 가능하다. (없다면 해당 값과 매칭해줄 수 있는 값이 없으므로 제외하면 된다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 총 시간복잡도는 O(NlogN)인데, 다른 풀이로는 그냥 정렬 후 투 포인터를 하는 방법도 있는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 투 포인터 방법은 제일 큰 값 기준으로 더했을 때 M이 되는 최솟값을 찾도록 하는 방법일 듯.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 13424 : 비밀 모임 - G4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Floyd-Warshall 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 방의 쌍에 대해서 최단거리를 탐색하고 모든 방들 중에 각 친구들이 있는 방까지의 거리 합이 제일 최소인 방을 찾으면 된다.&amp;nbsp; 각 친구들의 방에 대해서 다익스트라를 돌려도 풀 수는 있긴 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 테케별로 총 시간복잡도는 O(N^3). (K &amp;lt;= N 이라서 NK 는 N^3보다 작다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. BOJ 30049 : 영업의 신 - G4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation, Ad-hoc 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 매장별로 누적 매출액을 정렬된 상태로 관리할 수 있는 자료구조로 관리하면서 매장별 누적 매출 1위 직원이 누군지를 배열로 관리한다. 또한, 각 직원별로 누적 매출 1위를 한 매장 수를 배열로 관리하여 영업왕의 수가 처음에 몇 명인지를 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 각 쿼리별로 해당 매장의 누적 매출 1위가 변동될 때 누가 1등 했는지를 보면서 각 직원별로 누적 매출 1위를 한 매장 수를 업데이트 한다. 그러면서 영업왕의 수가 몇 명이나 바뀌었는지 확인하여 업데이트 하면 된다. 구현에 대해서 좀 생각해야하는 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ 30464 : 시간낭비 - G2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[i][j]를 i번 턴 했을 때에 j번째 칸에 도달할 때 까지의 최대 거리라고 생각하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 a[j]가 0 이상이므로 다음과 같이 식을 짤 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[0]에 대해서는 dp[0][j+a[j]] = max(dp[0][j+a[j], dp[0][j]+1) 이렇게 j = 1..N-1까지 탐색,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[1]에 대해서는 dp[1][j-a[j]] = max(dp[1][j-a[j]], dp[0][j]+1, dp[1][j] + 1) 이렇게 j = N-1...1까지 탐색.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[2]에 대해서는 dp[2][j+a[j] = max(dp[2][j+a[j]], dp[1][j]+1, dp[2][j] + 1) 이렇게 j = 1...N-1까지 탐색.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해서 dp[0][N], dp[2][N] 중 최댓값을 뽑아내면 된다.&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/100</guid>
      <comments>https://jun9985.tistory.com/100#entry100comment</comments>
      <pubDate>Wed, 26 Jun 2024 02:07:38 +0900</pubDate>
    </item>
    <item>
      <title>BOJ 랜덤 마라톤 후기</title>
      <link>https://jun9985.tistory.com/99</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 Solved.ac이 시즌 4를 맞이하면서 새로운 기능이 생겼습니다. 바로 랜덤 마라톤이라고 일종의 주간 미션입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;랜덤 마라톤은 말 그대로 일 주일 단위 랜덤디펜스를 한다고 생각하면 됩니다. 총 8 문제가 여러 난이도 분포에 맞추어 주어지며 일 주일 내로 해당 문제들을 푼다면 추가 별조각을 얻을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Solved.ac 내부적으로 랜덤디펜스를 돌릴 수 있는 기능이 있으면 좋겠다고 생각했는데, 이런 기능이 나타나서 매우 흥미로웠습니다. 이를 통해서 저도 좀 더 PS에 흥미를 다시 가질 수 있고 또 조금 침체되어있는 듯한 분위기도 좀 환기시킬 수 있지 않을까라는 기대도 해봅니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 잡소리는 여기까지 하고 제가 받은 마라톤 코스와 각 문제에 대해서 푼 후기를 남겨보도록 하겠습니다. 제가 받은 문제리스트는 아래와 같았는데, 궁금해서 F번은 미리 풀어보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;316&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGaQpT/btsH4C92WMh/pEN8EJ0Qgg4c9IZAUBIyW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGaQpT/btsH4C92WMh/pEN8EJ0Qgg4c9IZAUBIyW0/img.png&quot; data-alt=&quot;B1 ~ G2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGaQpT/btsH4C92WMh/pEN8EJ0Qgg4c9IZAUBIyW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGaQpT%2FbtsH4C92WMh%2FpEN8EJ0Qgg4c9IZAUBIyW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;894&quot; height=&quot;316&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;316&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;B1 ~ G2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 이 글을 쓰는 시각은 6월 18일 23:15로 나머지 문제들을 한 번 달려보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A : Cued In (Solved : 23:25)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Greedy + Math + Case-working(?) 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빨간 공의 개수 만큼 제일 높은 점수의 공을 여러번 치고 빨간 공이 다 빠지면 나머지 공들을 전부 치면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Snooker가 뭔지 몰라서 이해하는 데 좀 시간이 걸렸네요;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B : ポスター (Poster) (Solved : 23: 36)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;칸을 돌린 후에 색칠하든 칸을 색칠한 다음에 돌리는 것은 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 해당 포스터를 0, 90, 180, 270도로 회전을 시키고 그리고자 하는 포스터와 차이가 최대한 적은 걸 답으로 고르면 됩니다. (물론 회전 시키는 데 시간도 포함하구요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일본어 문제도 나올 지 몰랐는데;; ChatGPT 덕분에 풀 수 있었습니다. 그와 별개로 좋은 문제라고 느꼈습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C : 징검다리 건너기 (large) (Solved : 23:51)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Parametric Search로 풀었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;K를 파라미터로 두어 최솟값을 찾으면 되는데, 특정 K값에 대해서 1번째 칸에서 시작해서 N번째 칸으로 도달하는 경우가 존재하는 지를 파악하면&amp;nbsp; 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 DP로 풀려다가 Parametric Search도 가능해보여 선회했는데 DP로도 풀 수 있었더라구요... 연습을 더 해야겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그와 별개로 징검다리를 건널 때 뒤로도 갈 수 있는 걸 허용하여 DSU를 활용하도록 더하면 좀 더 재밌지 않았을 까 합니다. (물론 DSU로 풀 수 있다는 건 제 생각일 뿐 실제로 증명하진 않았습니다. 그런데 대강 O(N^2)로 돌들 끼리 이동할 수 있는 경우들을 undirected edge로 보아 그래프로 표현했을 때 1번 칸에서 N번 칸까지 갈 수 있는지 파악하면 되므로... DSU로도 풀 수 있을 것 같아요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D : NIKO (Solved : 00:35)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforcing + Implementation + Case-working으로 풀었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 보고 어떻게 풀지 감이 잘 안 와서 고민을 매우하였습니다. 일단 문제 형태를 보았을 때 가장 먼저 떠오르는 건 bruteforcing이나 greedy로 풀 것 같다라는 생각이 들었습니다. 실제로 보라매컵에서 bruteforcing 문제 느낌도 났었으니깐요. 그런데, 이게 어느 부분을 bruteforcing 할 지는 잘 감이 안 왔습니다. (3^22로 모든 선수의 포지션을 결정 짓는 작업만 해도 1초가 훨씬 넘어가요...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다가 문뜩 든 생각이 OV , VN, ON 인 선수들은 우선순위를 정하여 넣으면 되지 않을 까라는 생각이 들었습니다. 예를 들어 OV 선수를 보았을 때 V에 자리가 남아있으면 V에, 남아있지 않는 대신 O가 남으면 O에 넣는 식으로 우선순위를 bruteforcing하면 되지 않을까라는 생각이 들었습니다. 그래서 그렇게 풀어보니 실제로 문제가 풀렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;궁금해서 정해를 보았는데, 정해는 OV, VN, ON 각 선수들 중에서 몇 명을 O/V/N으로 보내고 나머지 몇 명을 다른 자리로 보낼지를 Bruteforcing해서 푸는 거라고 합니다. 제 풀이도 나름 비슷하게 풀었네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;E : Risk (Solved : 01:09)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 문제인 건 파악했는데... Input 포맷을 해석하는 것과 Output 포맷을 해석해서 맞추는 데가 좀 힘들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 내용은 그냥 BFS로 최단거리 구하는 무난한 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F : 작업 (예전에 풀었음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Topological Sorting + DP로 풀었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업들 간에 순서가 존재하고 모든 작업을 끝내는 데 걸리는 최소시간 구하기... ACM Craft 등에서도 많이 봤던 Topological Sorting + DP 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 제가 간과한 점이 있는데 이 문제에서는 Topological Sorting이 사실상 이미 되어있는 상태로 입력이 주어지기 때문에 그냥 1번부터 N번 작업 순차적으로 돌아가면서 DP 테이블을 채워도 됩니다. 그래서 그냥 DP로 풀어도 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;G : Dragon Maze (Large) (Solved : 01:34)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS + DP 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제일 우선적으로는 최단경로를 보아야 하므로 이는 BFS로 찾을 수 있습니다. 그런데, 우리는 힘이 최대화 되는 최단경로를 보아야 하므로 DP[y][x] : (y,x)까지 갈 때에 얻을 수 있는 최대 힘 이렇게 DP 테이블을 세워서 이를 저장해야합니다. 갱신 방법으로는 BFS로 해당 칸을 발견했을 때 i) 처음으로 발견했거나 ii) 아니면 발견했는 데 지금 발견한 경로도 최단거리일 경우 에 DP[y][x] = max(DP[y][x], DP[curr_y][curr_x] + power[y][x]) 이렇게 갱신해주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프를 좋아해서 그러는지는 몰라도 해당 문제도 좋은 문제라고 생각합니다. (여담이지만... G3에 재밌는 문제들이 많은 것 같아요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;H : 갈래 제곱 - 문제를 보니 적분식을 아는가를 물어보면서 문자열 파싱 + 구현 위주의 문제인 걸 파악했습니다. 아마... 오른쪽에 있는 식을 적분하여 왼쪽 식이 나오는지 직접 구현하는 방법으로 푸는 것 같긴한데, 제가 좋아하는 유형이 아니라서 패스했습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이번 주 제 마라톤 기록은 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dXb8rE/btsH29HQ3lo/778OmA3KnKDU1TKlDVeI20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dXb8rE/btsH29HQ3lo/778OmA3KnKDU1TKlDVeI20/img.png&quot; data-alt=&quot;H번 일부러 안 풀긴 했지만... 혼자 안 풀어서 뭔가 그렇네요 ㅠ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dXb8rE/btsH29HQ3lo/778OmA3KnKDU1TKlDVeI20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdXb8rE%2FbtsH29HQ3lo%2F778OmA3KnKDU1TKlDVeI20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;324&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;H번 일부러 안 풀긴 했지만... 혼자 안 풀어서 뭔가 그렇네요 ㅠ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 이렇게 몰아서 문제를 풀어보니 재미있었습니다. 확실히 많이 쉬면서 실력도 좀 녹슬은 것 같습니다. 매일 1 문제씩 풀었는데 맨날 브론즈 실버만 풀어서 그런지 골드 문제들은 푸는데 시간이 좀 걸렸네요 ㅠㅠ 그래도 문제 셋도 복귀차 풀기도 좋았습니다. 그리고 문제들도 나름 가벼웠구요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 이번 마라톤을 풀면서 약간 아쉬웠던 점도 있었습니다. 우선은 문제 푼 사람 수에 대한 커트라인도 정할 수 있으면 매우 좋았을 것 같습니다. 제가 풀었던 문제들 상당 수가 푼 사람 수가 100명이 넘어가지 않았습니다. 그러면 해당 문제에 대해서 참고할 수 있는 솔루션이 매우 적어져서 못 풀었을 경우에 복기하기가 매우 어렵습니다. 실제로 제가 뭣도 모르고 실랜디를 돌렸을 때 본 BOJ 7475번은 못 풀어서 어떻게 푸나 한 번 인터넷에 찾아보았는데도 솔루션이 나오지 않았습니다. (그래서 해당 문제는 아직도 못 풀었습니다. 특히나 NEERC 2003에 나온 엄청 옛날 문제라 그런지... 공식 홈 솔루션도 안 보여요... 그래도 어디 중국 사이트에 솔루션이 올라온 것 같긴 합니다.) 그래서 문제 푼 사람의 수를 좀 더 많은 문제들을 추천해주면 좋을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상 BOJ 랜덤마라톤 후기였습니다. 이제부터 다시 공부 열심히 해보겠습니다.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/문제 풀이</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/99</guid>
      <comments>https://jun9985.tistory.com/99#entry99comment</comments>
      <pubDate>Wed, 19 Jun 2024 01:52:40 +0900</pubDate>
    </item>
    <item>
      <title>2024.05.06. ~ 2024.05.12.</title>
      <link>https://jun9985.tistory.com/98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제.&lt;br&gt;&amp;nbsp;&lt;br&gt;1. BOJ 14450 : Hoof, Paper, Scissors (Gold) - G3&lt;br&gt;DP 문제.&lt;br&gt;&amp;nbsp;&lt;br&gt;DP 테이블을 dp[몇 번 손을 바뀌었는가][현재 낸 손 상태][몇 번째 소까지 상대 한 상태] 이런식으로 구상하고 테이블에 해당 상태에서 최대 이기는 횟수를 저장하도록 구성했다. 그렇게 DP 테이블을 구상하고 점화식을 세워보면 아래와 같은 경우들이 나온다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;dp[k][i][j] = max( dp[k][i][j-1], dp[k-1][0][j-1], dp[k-1][1][j-1], dp[k-1][2][j-1] ) + (현재 낸 손이 j번째 소를 이길 수 있으면 1, 아니면 0) // 각각 대충 설명하자면, 손 상태를 안 바꿀 때, 손 상태를 바꿀 때 이렇게 생각할 수 있다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;까먹고 계속 안 올리고 있다가 이제 올린다. 최근에 스트릭이 끊겼다. 그래서 겸사겸사 쉴 생각이다. 다음에 언제 또 올릴지는 모르겠지만, 적어도 스트릭 연명하는 건 다신 하진 않을 것 같다. PS는 하다보면 재미가 없어지는 때가 있는 것 같다. 그럴때 스트릭은 그저 숙제가 될 뿐이다. 나중에 블로그 글을 통해서 더 올려보고자 한다.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/98</guid>
      <comments>https://jun9985.tistory.com/98#entry98comment</comments>
      <pubDate>Sat, 18 May 2024 10:21:12 +0900</pubDate>
    </item>
    <item>
      <title>2024.05.14. OpenAI Spring Update 정리</title>
      <link>https://jun9985.tistory.com/97</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Google I/O가 열리기 전날에 OpenAI에서 Spring Update를 발표한다는 소식을 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 저도 AI에 대해 관심이 있는지라 라이브 영상을 보고 정리해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 이해한 내용들은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Desktop version of ChatGPT + WebUI update&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT를 데스크톱 어플리케이션으로도 만들었다고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 웹에서는 ChatGPT에 대한 경험에 좀 더 몰두할 수 있게 UI 개선이 이루어졌다고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. GPT-4o 라는 새로운 모델을 공개했습니다. 그리고 무료로 열린다고 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실상 이번 발표에 핵심 주제입니다. GPT-4o라는 모델을 새로 공개했는데 특징들은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Omnimodel이라는 말에 맞게 Voice + Text + Vision을 섞어서 활용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;GPT-4에 비해서 빠르면서 무료로 제공된다고 합니다.&lt;/li&gt;
&lt;li&gt;50가지 언어로도 가능합니다.&lt;/li&gt;
&lt;li&gt;GPT-4o의 API도 공개할 건데 두 배 더 빠르고 비용도 절반정도 든다고 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 실제 데모들을 시연하면서 추가적으로 어떤 기능들이 가능한지도 설명해주었는데, 각 데모별로 어떤 기능들이 있는지는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-1. Voice Dialogue Demo (GPT-4o와 말로써 대화하는 장면, 이야기를 읽어달라고 부탁함.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Real-time response 및 response 생성 중에 끼여들어 말하는게 가능합니다.&lt;/li&gt;
&lt;li&gt;목소리에 감정 표현 및 감정을 담아서 목소리를 내는게 가능합니다.&lt;/li&gt;
&lt;li&gt;여러명이 이야기 및 명령을 내려도 그걸 다 이해하는게 가능합니다.&lt;/li&gt;
&lt;li&gt;노래도 가능해보입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-2. Video Dialgoue Demo (GPT-4o와 목소리로 대화하다가 영상을 틀어 수식을 적고 이를 어떻게 풀지 힌트를 달라 부탁함.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카메라를 통해서 보여주며 서로 소통이 가능합니다.&lt;/li&gt;
&lt;li&gt;OCR도 가능합니다. 하트 같은 이모티콘 및 모형도 이해할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-3. Coding related Dialgoue Demo (GPT-4o에게 코드와 화면을 공유해서 코드 관련 이야기를 나눠봄.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴퓨터 내부의 코드를 복붙해서 GPT-4o에게 보내주고 GPT-4o는 함수 단위로도 요약 및 설명하는게 가능합니다.&lt;/li&gt;
&lt;li&gt;또한 화면을 공유하면서 도표를 보여주었는데, GPT-4o는 그걸 이해하고 요약 및 해석하는 것도 보여주었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-4. Translation Demo (이 부분은 청중들이 한 번 보여달라해서 보여준 데모입니다.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;번역기로 활동하라 명령한 상태에서, 영어와 이탈리아어 음성을 받았을 때 서로 다른 언어로 말해서 통역하는 걸 보여주었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-5. Emotion Recognition Demo (이 부분도 청중들이 한 번 보여달라해서 보여준 데모입니다.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;얼굴 사진을 통해서 해당 사람이 느끼는 감정을 판단해주는 것도 보여주었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 정리할 수 있습니다. (제가 영어 듣고 이해한대로 적은지라 좀 틀릴 수는 있습니다. 지적해주시면 감사드리겠습니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 대한 제 생각을 말해보면... 와 AI 분야는 제가 생각한 그 이상으로 매우 발전한 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영상을 보면서 계속 놀랐습니다. 제가 아는 AI 모델들은 이렇게 대답을 빠르게, 그리고 똑똑하게 답변할 줄 모르는 얘들이었는데, 영상에서 보여준 GPT-4o는 답변도 매우 빠르면서도 정확하게 답변했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, GPT-4o는 Text에만 국한되지 않고 Vision + Voice도 포괄하여 다루었던 점도 매우 인상적이었습니다. 데모에서 GPT-4o가 Text -&amp;gt; Voice, Vision -&amp;gt; Text -&amp;gt; Voice 이렇게 여러 도메인을 왔다갔다하면서 사람들과 서로 이야기하면서 유저들이 원하는 바를 이끌어내는데, 그렇게 자연스럽게 도메인들을 왔다갔다하는 것도 매우 신기했습니다. 이러한 점들은 multi-modal learning에 대해서 공부하는 사람들이라면 좀 더 재밌게 보았을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 제가 느낀바를 정리하자면 이번 발표는 OpenAI가 제대로 Google에게 한 방을 먹인 것 같습니다. 다음날 Google I/O를 준비하는 입장이라면 매우 화가 날 것 같은 발표였습니다. 다음에는 Google I/O도 한 번 보고 정리해보겠습니다. 대강보니 Google I/O에서도 이와 비슷한 AI를 준비한 것 같더라구요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI &amp;amp; ML &amp;amp; DL/정리</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/97</guid>
      <comments>https://jun9985.tistory.com/97#entry97comment</comments>
      <pubDate>Thu, 16 May 2024 05:43:46 +0900</pubDate>
    </item>
    <item>
      <title>왜 히스토그램 문제는 O(N)인가?</title>
      <link>https://jun9985.tistory.com/96</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;너무 뻔한 이야기 일 수도 있지만, 올해 들어서 이해했기에 글로 남겨봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PS를 꾸준히 풀다가 보면, &lt;a href=&quot;https://www.acmicpc.net/problem/1725&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;히스토그램&lt;/a&gt;이라는 문제를 한 번쯤은 들어봤을 수 있습니다. 플레 5 기준으로 사실상 제일 많이 풀린 문제이기도 하고 종만북, 바킹독 문제 모음집 등에서도 볼 수 있는 만큼 매우 유명한 문제이며 풀이도 여러 방법이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할 정복, 세그먼트 트리 등등의 여러 방법도 있지만 그래도 제일 유명한 풀이는 스택 풀이입니다. Monotone Stack 테크닉을 통해서 스택에 필요한 정보들만 남겨서 푸는 방법인데, 이렇게 풀면 O(N)으로 풀 수 있다고 알려져 있습니다. 그런데, 저는 이 문제를 풀면서 왜 이게 O(N)인지가 궁금했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 제 구현 상에서 핵심 아이디어 코드만 따서 보면 이렇게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1715018223073&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for(int i =0; i&amp;lt;N; i++){
    while(!stck.empty()){
        ll val, idx;
        tie(val, idx) = stck.back();
        if(val &amp;gt; v[i]){
            get&amp;lt;1&amp;gt;(v2[idx]) = i-1;
            get&amp;lt;0&amp;gt;(v2[i]) = get&amp;lt;0&amp;gt;(v2[idx]);
            stck.pop_back();
        }
        else {
            if(val &amp;lt; v[i]){
                get&amp;lt;0&amp;gt;(v2[i]) = idx;
            }
            else get&amp;lt;0&amp;gt;(v2[i]) = get&amp;lt;0&amp;gt;(v2[idx]);
            break;
        }
    } // stack 내부 아이템과 비교
    stck.push_back({v[i], i}); // stack에 현재 아이템 삽입
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 위의 코드를 보면 알겠지만 제 구현 상에서는, 각 아이템을 한 번씩 볼 때 중간에 while문 등으로 스택 내부에 있는 아이템과 비교하는 작업을 진행합니다. 그렇다면 각 아이템을 한 번씩 볼 때 중간 while 문에서 작업을 여러번이 가능하니 사실 O(N)이 아닐 수 있지 않을까요? while 문 내에서 작업하는 횟수가 유의미하게 커지는 일이 있을 수 있지 않을까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런 생각이 들어서 꽤 오랫동안 증명할 방법을 생각해보았는데, 올해 들어서 너무 단순하게 증명이 가능함을 알았습니다. 이제 while 문의 로직 구조를 본다면 아래와 같이 정리가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1715018439967&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;while(!stck.empty()){
    ll val, idx;
    tie(val, idx) = stck.back();
    if(val &amp;gt; v[i]){ // 현재 스택에 마지막으로 남은 아이템이 불 필요한가?
        get&amp;lt;1&amp;gt;(v2[idx]) = i-1;
        get&amp;lt;0&amp;gt;(v2[i]) = get&amp;lt;0&amp;gt;(v2[idx]);
        stck.pop_back();
    } // 불필요시 pop
    else {
        if(val &amp;lt; v[i]){
            get&amp;lt;0&amp;gt;(v2[i]) = idx;
        }
        else get&amp;lt;0&amp;gt;(v2[i]) = get&amp;lt;0&amp;gt;(v2[idx]);
        break;
    } // 필요시 loop를 끝내고 현재 아이템을 push
}
stck.push_back({v[i], i});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 본다면 &lt;b&gt;&lt;u&gt;while문이 한 번 돌 때마다 스택의 마지막 아이템을 pop 하거나, 아이템을 push&lt;/u&gt;&lt;/b&gt; 하게 됩니다. 그래서 &lt;u&gt;모든 아이템을 보았을 때&lt;/u&gt;&lt;u&gt;&lt;b&gt;&amp;nbsp;while문이 총 돌아가는 횟수&lt;/b&gt;는&lt;b&gt; 아이템들을 최대 몇 번 pop + 최대 몇 번 push 하는 횟수&lt;/b&gt;&lt;/u&gt;가 됩니다. 각 아이템은 한 번 씩 push 되고, pop이 된 후에는 더 이상 push될 일이 없습니다. 따라서, 각 아이템들은 각각 한 번 씩만 push / pop이 되므로 &lt;u&gt;모든 아이템을 보았을 때 while문에 대한 총 시간복잡도는 O(N)이 됩니다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 간단하게 증명이 되는 데 왜 이걸 생각하지 못했는지 놀랐습니다. 그래도 이렇게 생각이 나서 글로 정리해보았습니다. 인턴도 이제 슬슬 준비해야하는데 자소서 쓰기 귀찮아서 이렇게 글쓰기 연습이라는 명목하에 글을 써봤습니다 :)&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/기타</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/96</guid>
      <comments>https://jun9985.tistory.com/96#entry96comment</comments>
      <pubDate>Tue, 7 May 2024 03:06:13 +0900</pubDate>
    </item>
    <item>
      <title>2024.04.29. ~ 2024.05.05.</title>
      <link>https://jun9985.tistory.com/95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 4 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 1256 : 사전 - G2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP + Combinatorics 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가능한 모든 문자열의 개수는 N+M C M 이 된다. 그러면 현재까지 i개의 a와 j개의 z를 사용했다면 가능한 나머지 문자열들의 개수는 N+M-i-j C M-j가 된다. 이를 활용한다면 현재 자리에 a를 박았을 때 가능한 나머지 문자열들의 개수가 K 미만이라면 z를 꼭 사용하도록 구현해서 풀면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 모든 이항 계수를 DP 테이블로써 미리 계산을 해두고 현재까지 i개의 a와 j개의 z를 사용한 상태에서 a를 하나 더 박을 시 즉, N+M-i-j-1 C M-j가 K 미만이라면 z를 사용, 아니라면 a를 사용해서 정답을 채워 나가면 된다. 이렇게 말로만 표현하니깐 뭔가 애매한듯... 그래도 G2 DP를 25분만에 푼 건 오랜만인 것 같아 기분이 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 19606 : Escape Room - G2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 있는 칸의 값이 y * x 꼴이 되는 칸들은 모두 갈 수 있다. 따라서 각 칸의 y * x를 계산해서 특정 칸에 도착했을 때 갈 수 있는 칸들을 미리 계산해둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 (1,1)부터 시작해서 이미 해당 칸의 값에 해당되는 좌표들을 탐색한 적이 있는지의 여부를 기준으로 탐색하면 된다. (같은 값을 이미 본 적이 있다면 중복해서 탐색하므로... 1차원 BFS를 이렇게 돌리면 된다.) 오랜만에 그래프 문제 풀고 싶어서 랜덤으로 뽑았는데 8분 컷났다. 아직 감이 안 죽어서 다행이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 1309 : 동물원 - S1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i 번째 우리에 사자를 배치하는 방법은 1. 아무에도 배치 X, 2. 왼쪽에 배치, 3. 오른쪽에 배치 이렇게 세 가지가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이를 각각 dp[0][i], dp[1][i], dp[2][i]라고 한다면 아래와 같은 점화식을 생각할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- dp[0][i] = (i-1번째 우리에 사자가 어떻게 배치가 되든 상관이 없으므로) dp[0][i-1] + dp[1][i-1] + dp[2][i-1]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- dp[1][i] = (i-1번째 우리에 사자가 왼쪽에 배치가 되는 경우는 제외해야 함) dp[0][i-1] + dp[2][i-1]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- dp[2][i] = (dp[1][i]와 같은 원리) dp[0][i-1] + dp[1][i-1]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 점화식을 세우고 dp[0][N] + dp[1][N] + dp[2][N] 을 출력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 31797 : 아~파트 아파트 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math + Value Compression 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상대적인 위치만 알면 되므로 2*M 배열로 상대적인 위치만 기록해둔다. 이때 값 압축을 하면 되는데, 위치 값이 1 ~ 10000 이므로 그냥 10000 크기의 배열에 기록하고 나중에 한 번 훑어봐서 상대적인 위치들을 파악하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에는 몇 바퀴 도는 건지는 상관이 없으므로 (N-1) % (2*M)으로 위치를 바로 파악할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/95</guid>
      <comments>https://jun9985.tistory.com/95#entry95comment</comments>
      <pubDate>Mon, 6 May 2024 16:51:01 +0900</pubDate>
    </item>
    <item>
      <title>2024.04.22. ~ 2024.04.28.</title>
      <link>https://jun9985.tistory.com/94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 5문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 31713 : Double Up - S4&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math + Ad hoc + Hash map 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a가 홀수라면, 2^k * a 형태로 나타낼 수 있는 모든 수들끼리는 같은 수로 만들 수가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 활용해서 모든 수를 2로 나눌 수 있을 만큼 나눈다음 같은 수들끼리 묶어보면 가장 많이 등장하는 수의 최대 등장 횟수를 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 3644 : 그래프 매칭 - G3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n = 3, 4, 5, 6일 때의 경우의 수를 보니 C_n = C_n-1 + C_n-2로 피보나치 점화식 형태로 표현됨을 파악했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 그대로 대입해보니 정답이 나왔다;;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 알아보니 이렇게 초항이 0,1이 아닌 수에서 피보나치 점화식 형태로 표현되는 수열을 뤼카 수열이라고 한다 하더라.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 나쁘진 않았는데 다만 수 전체를 출력하지 않고 10^9+7로 나눈 나머지를 구하던지로 바꿨다면 더 좋은 문제였을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 2560 : 짚신벌레 - G3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i번째 날에 태어나는 짚신벌레의 수는 i번째 날에 태어난지 a번째 날이 되는 짚신벌레의 수부터 b-1번째 날이 되는 짚신벌레의 수들의 합이 된다. 그래서 dp[0] = 1로 초기화 하고 dp[i] = dp[i-a] + ... + dp[i-b+1] 이렇게 점화식을 세워서 풀면 되는데, dp[i-a] + ... + dp[i-b+1]은 Sliding Window 테크닉으로 계속 갱신하면서 풀어도 되고... 아니면 걍 오버킬로 Segment Tree로 풀어도 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 시간복잡도는 O(N). (Segment Tree는 O(NlogN)) 재밌는 DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 20365 : 블로그2 - S3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Greedy 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실상 R이나 B중 하나는 그냥 한 번으로 모든 색깔로 칠할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에는 나머지 색깔은 연속된 구간의 개수 만큼 꼭 칠해야 하니 연속된 구간들의 개수들을 세어 풀면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 31422 : AND, OR, XOR 2 - G1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bitmasking, Combinatorics, Prefix Sum 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AND, OR, XOR는 각 비트별로 독립적으로 계산되므로 비트별로 따로따로 계산해서 이를 합쳐도 무관하다. 각각 비트별로 따로 보면 아래와 같이 생각할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 구간의 AND의 결과로 i번째 비트가 켜졌다면 해당 구간에서의 i번째 비트는 모두 1이어야 한다. 따라서, j번째 원소의 i번째 비트가 1이라면 연속된 구간의 길이를 찾아서 [...j]의 구간 AND결과가 i번째 비트에 1이 들어오는 구간들의 개수를 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OR 같은 경우는 특정 구간에 1이 하나만 있으면 되므로 j번째 원소를 포함해서 0이 연속되는 구간을 빼고 나머지 경우의 수들을 전부 더해주면 된다. 따라서 j번째 원소를 포함해 1이 마지막으로 언제 나왔는지를 기록한다면 [...j]의 구간 OR 결과가 i번째 비트가 1인 경우의 수들을 모두 구해줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;XOR 같은 경우는 구간의 i번째 비트가 홀수 만큼 켜져있다면 1이 되므로 Prefix Sum을 활용해서 [...j]의 구간 XOR의 결과로 i번째 비트가 1인 경우의 수들을 모두 구해줄 수 있다. [1..j]의 i번째 비트가 홀수 개수만큼 켜져있다면 짝수 개수만큼 켜지는 구간들의 개수를 빼면 경우의 수가 나오고, 역으로 짝수 개수만큼 켜져있다면 홀수 개수만큼 켜지는 구간들의 개수를 빼면 경우의 수들이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주에 풀었을 때 제일 뿌듯했던 문제. 아직 폼이 아에 뒤진건 아닌것 같아 다행이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/94</guid>
      <comments>https://jun9985.tistory.com/94#entry94comment</comments>
      <pubDate>Mon, 29 Apr 2024 02:03:38 +0900</pubDate>
    </item>
    <item>
      <title>2024.04.15. ~ 2024.04.21.</title>
      <link>https://jun9985.tistory.com/93</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 4 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 20052 : 괄호 문자열 ? - P4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Prefix Sum + Segment Tree 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'('를 +1, ')'를 -1로 치환해서 푸는 문제인데, 옳은 문자열이라면 저렇게 치환했을 때의 총합은 0이어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 중간에 누적합의 결과가 음수가 나온다면 ')'의 개수가 더 많아지는 경우가 생기므로 옳은 문자열이 될 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, Prefix Sum을 미리 구하고 이에 대해서 Segment Tree를 생성하면 Min query로 중간 누적합 결과가 음수가 나오는지 판별도 쉽게 가능하다. Prefix Sum을 이미 구했으니 총합이 0이 되는지의 여부도 쉽게 파악이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 풀어본 세그 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 26093 : 고양이 목에 리본 달기 - G3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[i][j]를 i번째 고양이에게 j번째 리본을 달았을 때의 만족도 합의 최댓값이라고 하자. 그렇다면 dp[i][j] = a[i][j] + max(dp[i-1][k] (1 &amp;lt;= k &amp;lt;= K and k != j)) 이런식으로 점화식을 세울 수가 있다. 그런데, 이렇게만 점화식을 세우고 푼다면 O(NK^2)라서 TLE가 난다. 따라서, i-1번째 고양이가 j번째 리본을 단 케이스를 제외한 것 중에서의 최댓값을 빠르게 구해야하는데, 이를 multiset을 활용해서 O(logK)만에 구할 수 있다. 따라서 총 시간복잡도는 O(NKlogK).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재밌던 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 11725 : 트리의 부모 찾기 - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 트리의 부모찾는 문제로 트리의 루트부터 DFS를 하여 찾는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직도 트리 관련 문제를 50문제 이상 안 풀었어서 푼 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 31713 : 행운을 빌어요 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3*A &amp;lt;= B &amp;lt;= 4*A를 만족한다면 모든 줄기 및 잎을 사용해서 클로버를 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 활용해서 A와 B의 값을 하나하나씩 올려 풀면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의외로 이렇게 구현했는데 풀려서 놀랐던 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요새 문제 푸는게 약간 버거운 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에도 Lumine 작업도 계속 미뤄두고 있고... 좀 반성이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 이번 주 일지도 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/93</guid>
      <comments>https://jun9985.tistory.com/93#entry93comment</comments>
      <pubDate>Tue, 23 Apr 2024 04:49:32 +0900</pubDate>
    </item>
    <item>
      <title>2024.04.08. ~ 2024.04.14.</title>
      <link>https://jun9985.tistory.com/92</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 6 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 22251 : 빌런 호석 - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Bruteforcing 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 숫자간에 7개의 표시등 중에서 몇 개나 차이가 나는지를 미리 계산을 해둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 1 ~ N까지 숫자에 대해서 X와 표시등의 차이가 1개 이상 P개 이하인 숫자들을 모두 찾아보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표시등 개수의 차이는 각각 자리 별로 비교를 해보면 되니, 총 시간복잡도는 O(NK)가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 16876 : 재미있는 숫자 게임 - G2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Game Theory + DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;M번째 턴이 끝난 순간에 결과가 0~N이라면 cubelover, N+1 ~ 9999 이면 koosaga가 이긴게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 M번째 턴이 짝수면 cubelover, 홀수면 koosaga의 턴일텐데, cubelover의 턴일 경우에는 M-1번째 턴이 끝난 순간의 결과들 중 0 ~ N으로 만들 수 있는 수면 해당 수는 cubelover가 확정적으로 이기고,아니면 koosaga가 이기는 수가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역으로, koosaga의 턴일 때에는 M-1번째 턴이 끝나는 순간의 결과들 중 N+1 ~ 9999로 만들 수 있는 수면 koosaga가 이기는 수가 된다. 못 만든다면 cubelover가 이긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 역순으로 M번째 턴이 끝나는 순간부터 처음 시작하는 수까지 O(40000 * M) DP를 돌려보면 처음 수가 N인 경우 누가 이기는지를 파악할 수 있다. 총 시간복잡도는 O(40000 * M)이다. Game Theory DP를 많이 안 풀어본 입장으로써 입문하기 좋은 문제라 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 10610 : 30 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Greedy + Sorting + Math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;30의 배수가 되는 조건은 10의 배수가 되면서 3의 배수가 되면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 10의 배수가 되는 조건은 맨 끝자리 수가 0이면 되므로 (0, 10, ... 등등.) 0이 있는지의 여부로 판별하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3의 배수는 모든 자리 수를 합쳤을 때 3의 배수라는 특징을 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 모든 자리수들을 보았을 때 0이 존재하며 각 자리 수의 합이 3의 배수임을 확인하면 30의 배수가 되는 수를 만들 수 있음을 알 수 있는데, 그 중에서 제일 큰 수는 사실상 각 자리 수를 내림차순으로 정렬한 결과가 된다. (내림차순으로 정렬하면 제일 마지막 수는 0이 오므로 10의 배수가 되며, 3의 배수는 모든 자릿수의 합과 관련이 있어서 정렬 순서와는 관련이 없다.)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참관 알바하러 가면서 폰으로 풀었는데, 꽤 괜찮았던 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 15663 : N과 M (9) - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Backtracking 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현이 약간 귀찮은데, 나는 중복되는 순열을 set으로 전부 처리해서 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에는 그냥 Backtracking + 배열로 중복 방문을 하지 않도록 처리해서 풀면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 17836 : 공주님을 구해라! - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math + BFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공주와 전설의 검까지 가는 최단거리는 BFS를 통해서 각각 구할 수 있고, 전설의 검을 얻으면 공주까지 맨허튼 거리만큼 빨리 갈 수 있다. 그래서 BFS를 한 후에 검을 얻고 가는게 이득인지 아닌지를 판별하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에 엄청 많이 틀렸었던 문제. 바로 풀어서 감회가 새로웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. BOJ 23632 : 쿠키런 킹덤 - G1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Topological Sorting + Implementation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 지어진 건물들 중 한 건물이라도 a라는 자원을 생산할 수 있다면 a 자원은 0초만에 무한히 생성이 가능하니 a만 있으면 건설이 가능한 건물들은 모두 지을 수 있다. 이를 활용해서 indegree를 재료 개수로 생각하면서, 각 건물을 건설할 때 처음으로 특정 자원을 생산할 수 있다면 이와 관련된 건물들의 indegree를 하나씩 차감하면서 Topological Sorting을 돌리면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Topological Sorting 아이디어는 어렵지 않게 나왔으나 구현에서 약간 애먹은 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/92</guid>
      <comments>https://jun9985.tistory.com/92#entry92comment</comments>
      <pubDate>Tue, 16 Apr 2024 03:23:09 +0900</pubDate>
    </item>
    <item>
      <title>2024.04.01. ~ 2024.04.07.</title>
      <link>https://jun9985.tistory.com/91</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 3 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 16953 : A &amp;rarr; B - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 숫자를 노드로 치환해서 BFS로 풀어줄 수 있다. 숨바꼭질 시리즈와 비슷한 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 숫자 범위가 매우 커질 수 있으므로 map은 필수인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 방법으로는 그냥 그리디로 B에서 A로 줄여나가는 방법도 있다 한다. (아마 2의 배수면 2로 계속 나눠주고, 끝이 1이면 1 빼고 10으로 나눠주고를 반복하는게 아닐까...?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 31738 : 매우 어려운 문제 - ?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N이 M이상이면 N!은 N * (N-1) * ... * M * ... 이렇게 계산이 되니 M의 배수가 된다. 따라서, N &amp;gt;= M이면 답은 항상 0이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N &amp;lt; M이면 그냥 실제 팩토리얼을 계산하면 된다. (M의 범위가 10^7 이하이므로 충분히 계산할 수 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 문제 난이도가 올라오진 않았는데... 한 B2 정도 되지 않을까...?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 3060 : 욕심쟁이 돼지 - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Simulation + Math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상황 자체를 구현해서 풀면 된다. 시복은 대강 모든 돼지들이 첫 날 1씩만 먹었을 때...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하루 뒤에는 4, 이틀 뒤에는 16, ... 이렇게 4^n 만큼 계속 커지므로, 대강 O(logN)번 씩만 시뮬이 돌아간다고 생각하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주는 뭔가 문제를 풀기 싫어서 거의 브론즈 문제들만 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다보니 현재까지 나온 B5들을 모두 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DPuSI/btsGpXvhJ0y/X6cMYSgGJKPTyUFKvbRgxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DPuSI/btsGpXvhJ0y/X6cMYSgGJKPTyUFKvbRgxk/img.png&quot; data-alt=&quot;와! B5 올솔!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DPuSI/btsGpXvhJ0y/X6cMYSgGJKPTyUFKvbRgxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDPuSI%2FbtsGpXvhJ0y%2FX6cMYSgGJKPTyUFKvbRgxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1041&quot; height=&quot;500&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;와! B5 올솔!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어... 이러면서 같이 후기를 남기자면 B5에 B5 이상의 난이도 문제들이 생각보다 많다고 느껴졌다. 물론 어느정도 백준 푼 사람들에게는 별 차이 없어 보이겠지만... 뭔가 다른 B5보다도 어려운 문제들도 종종 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 B5에만 있는 이상한 문제들도 상당히 많았다. 깡 출력 문제까지는 이해가 되는데, 도대체 왜 Ada, Golfscript, FreeBASIC 같이 백준이 아니면 별로 쓸 일이 많이 없을 것 같은 언어들로 제한을 걸어서 깡 출력을 요구하는 문제가 있는지 모르겠다. 저렇게 언어제한이 걸려있는 문제는 오로지 저 문제를 위해서 새로운 언어를 좀 공부해야 하는 상황이 생기는데, 그러한 수고로움은 매우 불필요하지 않나라는 생각이 든다. 그래도 덕분에 특이한 언어들도 맛볼수는 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝. 다음 주 부터는 다시 빡세게 공부해야지...&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/91</guid>
      <comments>https://jun9985.tistory.com/91#entry91comment</comments>
      <pubDate>Mon, 8 Apr 2024 15:13:55 +0900</pubDate>
    </item>
    <item>
      <title>2024.03.25. ~ 2024.03.31.</title>
      <link>https://jun9985.tistory.com/90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 13 문제.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;1. BOJ 17219 : 비밀번호 찾기 - S4&lt;br /&gt;Hash map 문제.&lt;br /&gt;그냥 Hash map에 주소값을 key로, 비밀번호를 value로 저장한 다음&lt;br /&gt;각 쿼리별로 대답해주면 된다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;2. BOJ 28705 : RLE Inversion Counting - P3&lt;br /&gt;Math(Combinatorics) + Segment Tree + Value Compression 문제.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;일단 값의 범위가 매우 크므로 값 압축은 당연히 필요하다.&lt;br /&gt;그리고 지금 K번 이어붙이는 수열이 아닌 전에 이어붙인 수열과에서는 그냥 각 element 별로 inversion counting 결과값이 m_i이라면 m_i * K로 전부 더해주면 된다. 이는 Segment Tree로 가능하다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;그런데 이제 문제는 K번 이어붙이는 같은 수열 내부에서의 inversion counting인데, 두 가지의 경우의 수들을 살펴보아야 한다. 현재 i번째 element에 대하여&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;i번째 element보다 앞에 있으면서 값이 더 큰 element의 개수가 j개라면 총 j * (K * (K+1) / 2)를 더하면 된다.&lt;/li&gt;
&lt;li&gt;i번째 element보다 앞에 있으면서 값이 더 작다면, 두 번째로 이어붙이는 경우에는 i번째 element가 더 앞에 있게 되므로 개수가 j라면 j * (K * (K-1) / 2)를 더하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 Segment Tree 3개를 관리하는 방법으로 나는 풀었다. (사실상, 값 압축 Segment Tree 1개, PBDS 2개)&lt;br /&gt;구현량이 비교적 많아 잠오는데 풀기 귀찮았다...&lt;br /&gt;&amp;nbsp;&lt;br /&gt;3. BOJ 5529 : 저택 - P4&lt;br /&gt;Dijkstra + Implementation 문제.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;각 스위치와 시작 및 끝나는 곳을 노드로써 생각을 해보면, 상하좌우로 이동시에 처음으로 만나는 노드끼리만 연결 + 간선의 비용 == 거리로 두어 가중치가 있는 그래프로 구성할 수 있다. (상하좌우로 이동가능한 모든 노드끼리 연결할 필요는 없다. 왜냐면 결국에는 근처에 있는 노드를 거쳐서 가기 때문에...) 또한, 현재 문제를 그러면 가중치가 존재하는 그래프에서 {1,1}에 해당하는 노드에서 {N,M}에 해당하는 노드까지의 최단거리 계산하는 문제가 된다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;그래서, 최단 거리를를 계산하는 배열을 상하로만 문이 열렸을 때와 좌우로만 문이 열렸을 때 따로 계산해서 Dijkstra를 돌리면 되는데, {1,1} 에도 스위치가 존재할 수 있으니 {1,1}는 스위치 여부에 따라서 스위치를 누른 상태를 계산할 지 따로 예외처리 해주면 된다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;구현이 까다로웠던 문제. 아이디어는 그래도 어느정도 빨리 생각해낸것 같은데... 최적화 및 구현이 어려웠다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;4. BOJ 31631 : :rightplant: - G3&lt;br /&gt;Ad hoc + Constructive 문제.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;관찰을 통해서 i번째 빌딩에 대한 B_i는 왼쪽에 i번째 빌딩보다 높은 빌딩들의 높이 합 을 L_i, 오른쪽에 i번째 빌딩보다 높은 빌딩들의 높이 합을 R_i라고 하면 min(L_i, R_i)에 따라서 B_i가 정해지는 걸 알았다. 그래서 L_i와 R_i를 최대한 균등하게 맞춰주면 되는데, 이를 N부터 시작해서 1까지 순서대로 R_i와 L_i를 계산하면서 삽입해주면 된다.&lt;br /&gt;&lt;br /&gt;5. BOJ 1311 : 할 일 정하기1 - G1&lt;br /&gt;Bit DP 문제였다.&lt;br /&gt;&lt;br /&gt;현재 i번째 사람까지 어떤 일들을 맡았을 때 최소 비용을 저장하면 된다. 이는, i-1번째 사람까지 어떤 일들을 맡고 i번째 사람이 아직 안 고른 일들 중 하나 고르는 걸로 계산하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 DP식은 대강 dp[j|curr][i] = min(dp[j|curr][i], dp[j][i-1] + cost[k][i]) // which = (1 &amp;lt;&amp;lt; k) 이런식으로 세울 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;별해로 MCMF로도 풀린다고 한다.&lt;br /&gt;&lt;br /&gt;6. BOJ 9461 : 파도반 수열 - S3&lt;br /&gt;DP 문제였다.&lt;br /&gt;예전에 점화식을 본 기억이 있어 쉽게 풀었다.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;7~13. [GEC-Cup 2024 Open Contest] - (Solved : 7/10)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ 31668 : 특별한 가지 - B4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Arithmetic 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파묻튀밥의 줄의 개수는 M / N, 각 파묻튀밥을 K 그램의 가지로 바꾸면 되므로 걍&amp;nbsp; K * M / N을 출력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭔가 요구하는 바에 비해서 지문에서 '파묻튀', '파묻튀밥' 같이 생소한 용어들을 사용해서 그런지 좀 읽기 어렵게 느껴졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. BOJ 31669 : 특별한 학교 탈출 - B3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Bruteforcing 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무도 순찰하지 않을 때 탈출하면 되므로 세로 줄이 모두 X일 때를 찾아보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리 어렵지 않은 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. BOJ 31670 : 특별한 마법 공격 - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[0][i]를 i번째 칸에 빔을 쏘지 않았을 때 i번째 칸까지 전부 커버하는 최소비용, dp[1][i]를 i번째 칸에 빔을 쏘았을 때 i번째 칸까지 전부 커버하는 최소비용 이렇게 정의를 하자. 그러면 점화식을 아래와 같이 세울 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;dp[0][i] = dp[1][i-1] (i-1번째 칸은 항상 커버해야 되므로...)&lt;/li&gt;
&lt;li&gt;dp[1][i] = cost[i] + min(dp[1][i-1], dp[0][i-1]) // i-1번째 칸은 커버하거나 말거나 상관없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 나중에 min(dp[0][N], d[1][N])을 출력해보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가벼운 점화식 DP 문제로 재밌게 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10. BOJ 31671 : 특별한 오름 등반 - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 BFS로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 어떻게 풀지 막막해서 다른 문제들을 풀다가, 그냥 BFS로도 풀릴 수 있다는 생각이 들어 BFS로 풀어보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(0 , 0)과 (2N , 0) 을 기준으로 BFS를 돌렸을 때 둘 다 도달할 수 있는 칸은 실제로 준석이가 등반할 때 도달할 수 있는 칸이 된다. 그래서 BFS를 두 번 돌려서 두 번 탐색된 좌표들을 찾고 이 중에서 제일 높은 y값을 출력하면 된다. (없으면 -1 출력)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;갑자기 BFS로도 풀 수 있다는 생각이 들었을 때 왜 이걸 빠르게 생각하지 못했나 현타왔었다. 이러면 안 되는데... 그나저나 별개로 타 BFS 문제들이랑 다르게 바로 떠오르는게 쉽지 않았던 문제였던 것 같기도 하다. (실제로 DP 풀이도 많이 나오고는 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11. BOJ 31672 : 특별한 케이크 (easy) - S3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Simulation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말 그대로 모순이 되는 케이스들을 전부 찾아서 이를 시뮬레이션을 굴려보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현 시뮬은 언제나 풀기 귀찮다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12. BOJ 31673 : 특별한 학생회장 교체 - S3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 Greedy + Sorting + Parametric Search로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학생회 예산을 mid로 잡았을 때, 반대표 개수가 높은 순서대로 남은 예산들 중 mid 만큼 계속 빼서 주었을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탄핵이 된다면 l = mid, 아니라면 r = mid로 잡아 최솟값을 찾으면 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 실제 태그는 그냥 Greedy + Sorting이라고 하는데, 생각해보니 정렬해서 그냥 과반수가 되는 학생 단체 개수의 최솟값을 찾고(이를 K라고 하자.) M / (K+1)를 출력하면 되긴 할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;13. BOJ 31674 : 특별한 기술력 - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 Ad hoc + Greedy + Sorting + Divide and Conquer(거듭제곱)으로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관찰을 해보니, 오름차순으로 정렬한 결과가 a1, a2, a3, ... an이라 하면 a1 + a2 * 2 + a3 * 4 + a4 * 8 + ... + an * (2^{n-1}) 가 최대가 됨을 알 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 2^n을 Divide and Conquer로 풀었는데, 이걸 그냥 변수로 하나 두어 매번 2를 곱하고 나머지를 다시 계산하는 방법으로 2^n을 좀 더 효율적으로 구할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/90</guid>
      <comments>https://jun9985.tistory.com/90#entry90comment</comments>
      <pubDate>Wed, 3 Apr 2024 00:52:40 +0900</pubDate>
    </item>
    <item>
      <title>2024.03.18. ~ 2024.03.24.</title>
      <link>https://jun9985.tistory.com/89</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 5 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 19587 : 객실 배치 - G1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP + Exponential by Squaring 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP[n]을 n층 건물을 채우는 방법의 수라고 식을 두면, DP[n] = 2 * DP[n-1] + DP[n-2] 이런 점화식이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 점화식은 사실 DP[1] ... DP[5] 까지 경우의 수를 그리면서 알게 된거긴 하지만, 점화식을 설명해보자면...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n층 건물은 n-1층의 건물에서 한 층 더 쌓아올린 거라고 생각해도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 우리가 생각해야할 경우의 수는...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- n-1층까지 쌓아올린 후에 n층에 아무도 살지 않는 경우의 수 = DP[n-1]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- n-1층까지 쌓아올린 후, n-1층 오른쪽에 아무도 안 사는 경우의 수 = DP[n-1] - n-1층 오른쪽에 사는 사람이 있는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- n-1층까지 쌓아올린 후, n-1층 왼쪽에 아무도 안 사는 경우의 수 = DP[n-1] - n-1층 왼쪽에 사는 사람이 있는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 모두 더 해보면... DP[n] = 3 * DP[n-1] - (n-1층 오른쪽에 사람이 사는 경우의 수 + n-1층 왼쪽에 사람이 사는 경우의 수) =&amp;nbsp; 2 * DP[n-1] + (n-1층에 사람이 아무도 살지 않는 경우의 수) = 2 * DP[n-1] + DP[n-2]가 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이 점화식을 기반으로 행렬을 세우고 분할 정복을 활용해서 O(logN)만에 거듭제곱을 시행하고 행렬곱을 해주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 12928 : 트리와 경로의 길이 - P4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP + Math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 경로가 2인 경로들 개수는 모든 노드에 대해서 해당 노드를 경로의 중간에 있는 노드라고 했을 때에, 해당 노드와 연결된 다른 두 노드를 선택하는 경우의 수들의 합이라고 할 수 있다. 1, 2, ..., N번 노드와 연결된 노드들의 개수 = 연결된 edge들의 개수를 각각 e_1, e_2, ..., e_N으로 표현하면 다음과 같이 식을 정리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;e_1 + e_2 + ... + e_N = &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;2*(N-1)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S = e_1C2 + e_2C2 +... + e_NC2 = (e_1^2 + e_2^2 + e_3^2+ ... + e_N^2)/2&amp;nbsp; - (e_1+e_2+...+e_N)/2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;e_1^2 + e_2^2 + e_3^2 +... e_N^2 = 2*S + 2*(N-1)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 우리는 n개의 노드들에 대해서 degree의 총 합이 2*(N-1)가 되도록 적절히 분배했을 때에 e_1^2 + e_2^2 + e_3^2 +... e_N^2 = 2*S + 2*(N-1) 를 만족하는 경우가 있는지를 파악해야 한다. 이를 위해서 DP식을 아래와 같이 세워두고 memoization을 돌려보면 쉽게 풀 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- dp[n][k][val] = n번째 노드까지 degree를 2*N-2-k개를 분배했고, e_1^2 + e_2^2 + e_n^2 = val 일때, 나머지 N-n개의 노드들로 e_1^2+ e_2^2 + ... + e_N^2 = 2*(S+N-1)를 만족하는 경우가 존재하는 가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 아이디어가 매우 재밌었던 문제. 이외에도 여러 다른 풀이가 존재하는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 21925 : 짝수 팰린드롬 - G3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Greedy +&amp;nbsp; Stack + Deque으로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 팰린드롬을 Greedy하게 가져갈 수 있는건 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약에 팰린드롬 S의 맨 앞에서부터 시작하는 substring s도 팰린드롬이라면 S는 s - &amp;lt;팰린드롬&amp;gt; - s 구조를 띄고 있을 것이다. 따라서, S를 s - &amp;lt;팰린드롬&amp;gt; - s 이렇게 세 개로 더 쪼갤 수 있기에 Greedy하게 가져갈 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, Stack과 Deque을 활용해서 뒤랑 같으면 pop, 아니면 empty가 되기 전에 pop했던 것들 전부 되돌리고 새로운 값을 push하는 방식으로 구현해서 팰린드롬 판별을 좀 더 쉽게 할 수 있다. 이렇게 구현하면 각 element 별로 최대 O(N)번 pop, push가 되므로 총 시간복잡도는 O(N^2)이 될거다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP랑 Greedy는 역시 연습을 더 해야겠다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 1289 : 트리의 가중치 - P3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tree DP + math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 노드별로는 해당 노드 아래 간선들을 지날 때 가능한 비용들의 합을 기록해야하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별개로 DFS를 하면서 서브트리 간의 가능한 경로들의 가중치 합도 따로 기록하면된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 DP로 플레 자력솔을 할 줄은 몰랐다. 그래도 내가 자력솔 할 정도면 P4도 될 수 있을 것 같아 P4로 기여해두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 14449 : Balanced Photo - P5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 Merge Sort Tree로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Merge Sort Tree로 구현한다면 쿼리 내에서 Binary Search를 돌려 구간 내에서 k보다 큰 값들의 개수를 쉽게 알 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 그냥 각 v[i] 별로 앞 뒤 구간의 v[i]보다 큰 값들의 개수를 찾아서 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정해는 Segment Tree라고 하는데... 좀 비슷하게 풀리지 않을까 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 13147 : Dwarves - G2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Topological sorting 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;난쟁이들 간의 키의 대소관계를 그래프로 나타내면, 대소관계가 꼬이는 경우 = 사이클이 존재하는 경우가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 해당 그래프가 DAG인지 아닌지를 확인하면 되므로 Topological sorting을 박아서 모든 정점의 indegree가 0이 되는지를 확인하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Topological sorting 연습하기 좋은 문제라 생각한다.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/89</guid>
      <comments>https://jun9985.tistory.com/89#entry89comment</comments>
      <pubDate>Tue, 26 Mar 2024 15:19:15 +0900</pubDate>
    </item>
    <item>
      <title>[Programmers] 더 맵게</title>
      <link>https://jun9985.tistory.com/88</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42626?language=cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42626?language=cpp&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1710706241349&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42626?language=cpp&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/H36gU/hyVBCuUvcE/yYmJNmFbBgCgNTjFBOxXg0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ozTEs/hyVAMEWYEk/b9ScFjv3tiQzv6KQvAaSd0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42626?language=cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42626?language=cpp&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/H36gU/hyVBCuUvcE/yYmJNmFbBgCgNTjFBOxXg0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ozTEs/hyVAMEWYEk/b9ScFjv3tiQzv6KQvAaSd0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제의 조건을 읽어봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 음식들의 스코빌 지수가 주어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 스코빌 지수가 제일 낮은 두 음식을 섞어서 스코빌 지수가 더 높은 음식 하나를 만들어 낼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 문제에서는 모든 음식의 스코빌 지수가 K 이상이 될려면 최소 몇 번 음식을 섞어야 하는지를 물어봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거 2021년 7월, 제가 입대하기 전에 풀었던 문제입니다. 그냥 필 받아서 다시 풀어보는데... 의외로 PS 지식 하나도 없었는데도 정상적으로 풀었습니다;;; 일단 이 문제를 풀기 위해서 우리는 어떤 기능들이 필요하냐면...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 현재 음식들 중에서 스코빌 지수가 가장 낮은 걸 빠르게 찾을 수 있어야 합니다. (Pop)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 두 음식이 섞인 새로운 음식을 넣은 후에도 스코빌 지수가 가장 낮은걸 빠르게 찾을 수 있어야 합니다. (Push)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 가지 기능들을 지원하는 자료구조나 알고리즘이 필요합니다. 이 두 가지 기능은 사실 Priority Queue로 O(logN)만에 해결이 가능합니다. 그래서 예전에 저는 Priority Queue를 파이썬에서 heapq 라이브러리 가져다가 풀었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이번에도 이렇게 풀면 재미없으니, 저는 이번에는 multiset으로 풀었습니다. multiset도 값을 넣는 것도 O(logN) 지우는 것도 O(logN)만에 지원이 됩니다. 다만 차이는, Priority Queue가 아마도 상수 시간이 덜 드는 걸로 알고 있습니다. 그래도 multiset은 lower_bound, upper_bound가 지원이 됩니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 multiset으로 푼 제 코드입니다. 음식은 최대 N-1번 섞을 수 있고, 섞을 때마다 O(logN)의 시간이 필요하므로 총 시간복잡도는 O(NlogN)이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1710706869601&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
#define ll long long

using namespace std;

int solution(vector&amp;lt;int&amp;gt; scoville, int K) {
    multiset&amp;lt;ll&amp;gt; ms;
    for(auto itr : scoville) ms.insert(itr);
    ll answer = 0;
    while(ms.size() &amp;gt; 1){
        ll val = *(ms.begin());
        if(val &amp;gt;= K) break;
        
        ll new_food = 0;
        auto itr = ms.begin();
        new_food += *itr;
        ms.erase(itr);
        itr = ms.begin();
        new_food += 2 * (*itr);
        ms.erase(itr);
        ++answer;
        ms.insert(new_food);
    }
    if(*(ms.begin()) &amp;lt; K) answer = -1;
    return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/문제 풀이</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/88</guid>
      <comments>https://jun9985.tistory.com/88#entry88comment</comments>
      <pubDate>Mon, 18 Mar 2024 05:21:16 +0900</pubDate>
    </item>
    <item>
      <title>[Programmers] 멀리 뛰기</title>
      <link>https://jun9985.tistory.com/87</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/12914?language=cpp&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://school.programmers.co.kr/learn/courses/30/lessons/12914?language=cpp&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;프로그래머스&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/12914?language=cpp&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/AHmRU/hyVBN4gTAS/clHeXmZykIZpOeUlqhkEuk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/HhAV8/hyVBIWcjuc/EFUB78UFwFEqz048ckPSUK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot; data-og-url=&quot;https://programmers.co.kr/&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/&quot; target=&quot;_blank&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/12914?language=cpp&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/AHmRU/hyVBN4gTAS/clHeXmZykIZpOeUlqhkEuk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/HhAV8/hyVBIWcjuc/EFUB78UFwFEqz048ckPSUK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;프로그래머스&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;programmers.co.kr&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;문제 조건을 보면 다음과 같습니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;1. 효진이는 한 번에 한 칸 혹은 두 칸을 갈 수 있습니다.&lt;br&gt;2. 그렇다면 효진이가 0번째 칸에서 시작해 n번째 칸까지 간다면 몇 가지의 방법으로 갈 수 있는지를 출력해야 합니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;이 문제를 읽어보자마자 예전에 백준에서 풀었던 숨바꼭질 시리즈, 1로 만들기 문제들이 생각이 났습니다.&lt;br&gt;사실 이 문제는 DP로 풀 수 있습니다.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;일단&lt;u&gt;&lt;b&gt; DP[k] = k 번째 칸까지 이동하는 방법의 개수&lt;/b&gt;&lt;/u&gt;라고 합시다. 그러면 k칸으로 도착하기 전에 도달했던 칸은 어디일까요?&lt;br&gt;바로 k-1칸과 k-2칸이 됩니다. 그렇다면 &lt;u&gt;&lt;b&gt;DP[k] = k-1칸까지 간 다음 한 칸 뛰어서 온 경우의 수 + k-2칸까지 간 다음 두 칸 뛰어서 온 경우의 수 = DP[k-1] + DP[k-2]&lt;/b&gt;&lt;/u&gt; 꼴이 됩니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;그러면 이제 우리는 다음과 같이 점화식을 세울 수 있습니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;&lt;b&gt;점화식 : DP[k] = DP[k-1] + DP[k-2] (for k &amp;gt; 2)&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;초기값 : DP[1] = DP[2] = 1&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이를 기반으로 이제 코드만 짜면 되겠죠? 실제 코드는 다음과 같습니다. DP[3]부터 DP[n]까지 한 번씩만 보면 되므로 시간복잡도는 &lt;b&gt;O(n)&lt;/b&gt;이 됩니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
#define ll long long

using namespace std;

long long solution(int n) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;long long answer = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vector&amp;lt;ll&amp;gt; v(n+1, 0);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v[1] = 1, v[2] = 1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(int i =1; i&amp;lt;=n; ++i){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(i+1 &amp;lt;= n) v[i+1] = (v[i+1]+v[i])%1234567;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(i+2 &amp;lt;= n) v[i+2] = (v[i+2]+v[i])%1234567;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;answer = v[n];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return answer;
}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이 문제도 예전에 풀었던 문제였는데... 예전에는 너무 이상하고 더 어렵게 풀었어서 다시 풀었습니다. 예전에는 한 번 뛴 횟수와 두 번 뛴 횟수가 정해지면 팩토리얼의 형태로 방법의 수를 계산할 수 있으니 한 번 뛴 횟수와 두 번 뛴 횟수를 계속 조정해가면서 풀었네요;;; 다만 저 문제를 풀었을 때가 2021년 11월, 제대로 PS를 해본 적이 없었던 때라서 그런지 오히려 제가 더 성장함을 느껴 뿌듯했습니다. (만약에 제가 2023년에 저 어지러운 방법으로 풀었다면 매우 반성했을 겁니다.)&lt;br&gt;&lt;br&gt;+) 이 글 올리고나서 저 점화식을 다시 보니 피보나치 수열 점화식이었네요;;; 어쩐지 낯이 익다 했습니다.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/문제 풀이</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/87</guid>
      <comments>https://jun9985.tistory.com/87#entry87comment</comments>
      <pubDate>Mon, 18 Mar 2024 05:05:06 +0900</pubDate>
    </item>
    <item>
      <title>[Programmers] 문자열 압축</title>
      <link>https://jun9985.tistory.com/86</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/60057?language=cpp#&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/60057?language=cpp#&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1710694496419&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/60057?language=cpp#&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vn6Oh/hyVAG5LcZp/y5YIDCo9HAsxeF0XiZSk90/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/d390g8/hyVyfaiteg/w2dpNg23StEDgysVFhXkP0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/60057?language=cpp#&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/60057?language=cpp#&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vn6Oh/hyVAG5LcZp/y5YIDCo9HAsxeF0XiZSk90/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/d390g8/hyVyfaiteg/w2dpNg23StEDgysVFhXkP0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제의 조건을 해석해보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 길이가 1000 이내의 문자열이 주어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 우리가 구하고자 하는 건 문자열을 제일 짧게 압축했을 시에 길이를 구하고자 합니다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;문자열을 압축하는 방법은 아래와 같은 절차를 따릅니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;2-1. 임의의 k를 골라 고정하고, 앞에서부터 k개의 문자씩 자릅니다. k개의 문자 단위를 &quot;구간&quot;이라고 합시다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;2-2. 자른 이후에 구간들 사이에서 연속되면서도 구간의 문자열이 동일하다면 하나로 합칠 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-3. 두 개의 이상 구간을 합쳤으면 &quot;구간의 수&quot; + &quot;해당 구간의 문자열&quot; 이런식으로 표기해서 압축합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 저는 먼저 길이가 1000 이내임을 먼저 확인해서 뭔가 브루트포싱으로도 풀리긴 하겠다는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열 길이가 N이라고 할 때에 1 ~ N의 길이별로 구간을 나누고... 이후에 전의 구간과 문자열이 동일하다면 하나로 압축, 아니면 해당 구간을 이제 기준으로 새롭게 압축 하는 방법으로 하면 되지 않을 까 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 그대로 구현했더니, WA가 나왔습니다. 왜 그런지 다시 생각을 해보니 제가 압축이 된다면 앞에 붙는 숫자가 한 자리 수라고만 생각해서 그랬었습니다. 실제로는 압축되는 구간이 1000개가 될 수도 있어서 최대 4자리 수가 더 붙을 수 있습니다. 그래서 구현을 좀 더 수정해서 제출했더니 AC를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 시간복잡도 분석에 들어가보겠습니다. 제 구현 상에서는 구간의 길이 k를 1부터 N까지 돌렸습니다. 그리고 내부에서는 문자열을 훑어보면서 구간이 끝날 때마다 전 구간과의 문자열 비교를 했습니다. 문자열 비교는 O(k)일 것입니다. 그런데, 이 문자열 비교는 O(N/k)번마다 진행을 합니다. 따라서 실제적으로 문자열 비교는 모든 k에 대해서 O(N)만큼 진행합니다. 그래서 총 시간복잡도는 Amortized O(N^2)으로 계산이 됩니다. N이 1000이면 충분히 1초 내로 시행이 됩니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 정답 코드는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1710695419988&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
#define ll long long

using namespace std;

int solution(string s) {
    ll answer = 1000;
    for(int i =1; i&amp;lt;=s.size(); ++i){
        string pat = &quot;&quot;;
        string curr = &quot;&quot;;
        bool flag = false;
        int idx =0 ;
        ll cnt = 0;
        ll ans = 0;
        for(char ch : s){
            if(!flag) pat += ch;
            curr += ch;
            ++idx;
            idx%=i;
            if(idx==0){
                if(!flag){
                    flag = true;
                    ans += i;
                    cnt = 1;
                }
                else{
                    if(curr == pat) ++cnt;
                    else{
                        if(cnt &amp;gt;= 1000) cnt = 4;
                        else if (cnt &amp;gt;= 100) cnt = 3;
                        else if (cnt &amp;gt;= 10) cnt = 2;
                        else if (cnt &amp;gt; 1) cnt = 1;
                        else cnt = 0;
                        ans += cnt+i;
                        pat = curr;
                        cnt = 1;
                    }
                }
                curr = &quot;&quot;;
            }
        }
        if(cnt &amp;gt;= 1000) cnt = 4;
        else if (cnt &amp;gt;= 100) cnt = 3;
        else if (cnt &amp;gt;= 10) cnt = 2;
        else if (cnt &amp;gt; 1) cnt = 1;  
        else cnt = 0;
        ans += s.size()%i + cnt;
        //cout &amp;lt;&amp;lt; ans &amp;lt;&amp;lt;&quot;\n&quot;;

        answer = min(answer, ans);        
    }
    
    return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에 파이썬으로 풀었던 기억이 있는 문제였는데, 다시 C++로 풀려니 좀 헷갈립니다. 뭔가 카카오는 구현 위주라도 뭔가 저랑 잘 안 맞는 느낌의 문제들만 나오는 것 같습니다. 특히나 시간복잡도 계산이 은근히 어려워서 어떤게 정해일지가 바로 파악하기 어려웠습니다. (이번 문제만 해도 레벨 2인데, 브루트포싱이 가능하냐 불가능하냐를 시간복잡도를 계산해서 알아내기는 다른 레벨 2보단 어려웠다고 생각합니다.) 그래도 이렇게 계속 풀다가 보면 징크스도 깨부술 수 있겠죠? 아무튼 처음으로 리뷰해보는 프로그래머스 문제였습니다.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/문제 풀이</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/86</guid>
      <comments>https://jun9985.tistory.com/86#entry86comment</comments>
      <pubDate>Mon, 18 Mar 2024 02:12:47 +0900</pubDate>
    </item>
    <item>
      <title>2024.03.11. ~ 2024.03.17.</title>
      <link>https://jun9985.tistory.com/85</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 12 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 25416 : 빠른 숫자 탐색 - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 시작점에서 BFS를 돌려서 모든 칸의 최단거리를 보고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 모든 칸을 보면서 그 중 1이면 최단거리가 얼마인지를 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크기가 5 * 5 고정이라 최단거리 초기화를 대강 30 정도로만 해도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(최대 25칸이나 지나야 최단거리라서... 사실 25칸도 무리라고 생각한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N = 5라고 하면 시간복잡도는 O(N^2)인데... N이 너무 작아서 사실상 O(1) 같은 느낌으로 풀린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 2417 : 정수 제곱근 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Binary Search 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 mid * mid &amp;gt;= N 인지로 Binary Search 돌리면 되는 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데, N의 범위가 매우 커서 l,r 범위를 잘 설정해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;귀찮아서 파이썬으로 제출했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 14868 : 문명 - P4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DSU + BFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 BFS를 돌리면서 처음으로 하나의 집합의 크기가 K가 될 때를 찾는 문제인데...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 합쳐지는 조건이 두 면이 맞대어 있거나 아니면 칸이 서로 겹치는 경우라서 좀 까다로웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국에는 한 칸이 다른 한 칸을 합칠 때 무조건 전이나 동시에 찾은 칸만 합치도록 설계해서 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계속 맞왜틀 당하다가 정 안 돼서 질문 게시판 봐서 반례를 찾았는데... 저기까지 생각이 미치지 못 했던게 좀 아쉬웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간제한이 매우 빡빡해서 Smaller-to-Larger까지 일단 넣어줬는데, 없이도 풀 수 있는 것 같긴하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 31565 : 전역 역전 - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Knapsack DP + Implementation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;휴가를 받아서 더 일찍 전역하는 것과 군기교육대나 전문하사로 상대의 전역일을 늦추는 건 상대적인 개념으로 보면 동일한 행위이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 여유를 weight로, 늦추는 기간을 value로 치환하여 Knapsack DP를 돌린 다음에 원래 전역일 차이에서 빼주면 된다. (음수가 나오면 -1를 곱해주어야 한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난주에 한 시간 남기고 풀기 시작한 전남대 PIMM 알고리즘 파티 E번 문제다. 당시에도 Knapsack DP임은 쉽게 눈치를 챘는데, 시간차이 계산 방법을 찾느라 시간내에 풀지 못했던 기억이 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그거와 별개로 지문 내용도 너무 무섭다. 이런 후임을 안 만나서 다행이라 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 1789 : 수들의 합 - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math + Greedy 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1+2+...+i &amp;gt; N 이라면, 1 + 2 + ... + (2*i-1) 이렇게 쪼개는 게 최선이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 되는 이유를 나름의 증명을 해보자면, 수가 작으면 작을 수록 서로 다른 자연수의 개수가 줄어든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 N -&amp;gt; N-1 -&amp;gt; N-1-2 이러한 순서대로 탐색하는게 서로 다른 자연수의 개수가 제일 많아지는 방법이라 생각하여 이렇게 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. BOJ 6813 : Signage - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Greedy + Implementation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단어 크기 합 + 단어 개수 - 1 &amp;lt;= w 가 되도록 한 문장을 만들어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에는 w - 단어 크기 합 만큼의 빈칸들을 단어 개수 -1 군데에 배분을 잘 해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이 부분은 수학으로 잘 배분해주면 된다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 내 구현에서는 단어가 딱 하나만 들어가는건 예외 처리가 필요하긴 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 Greedy 보다는 구현 문제에 더 가까운데, 구현이 그리 재밌지도 않아서 풀기 귀찮았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ 3197 : 백조의 호수 - P5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS + DSU 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 BOJ 14868처럼 BFS를 날짜별로 돌리면서 두 점의 부모가 언제 같아지는 지 확인하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS를 날짜끼리 구분해서 돌리는 건 큐 두 개를 관리하면서 구현하면 되고, 합치는 규칙은 현재 보고 있는 점과 같은 날에 녹았거나 좀 더 일찍 녹은 물과만 좌표를 합치면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시나 해서 Smaller to Larger도 같이 구현했는데, 빼고 다시 제출해보니 속도가 더 빨라서 신기했던 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그와 별개로 BFS + DSU 문제 기본 난이도가 이렇게 높은 줄도 몰랐다. (난 진심으로 G3 정도라고만 생각했었다;;;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. BOJ 11280 : 2-SAT - 3 - P4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SCC 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디코에 박아둔 백준 봇이 추천해서 따로 하고 있는 알고리즘 구현 플젝에 SCC도 추가할 겸 같이 공부해서 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OR 문에서 하나가 거짓이면 나머지는 꼭 참이라는 점을 그래프로 표현해서 SCC를 보고 모순을 찾는 게 신기했다. (SCC가 아니라 일방적으로 연결된거면 상관 없다.)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;~ x1은 x_{N+1} 이런식으로 그래프의 크기를 2*N로 설정해서 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. BOJ 11281 : 2-Sat - 4 - P3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SCC 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 BOJ 11280를 풀어보고 흥미가 생겨 같이 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 SCC를 타잔 알고리즘으로 짠 다음에 위상정렬을 하지 않고도 AC를 받았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 1번 노드부터 순서대로 DFS를 한 SCC들을 SCC를 구한 순서대로 보면서 가능한 SCC 내의 값을 True로 만들었더니 풀렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대강 이유로는 ~p -&amp;gt; q 이긴 하지만 p -&amp;gt; q 라도 상관은 없어서 그런 것 같은데... AC를 받고도 좀 찝찝했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10. BOJ 11277 : 2-SAT-1 - S1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforcing 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시리즈가 있어서 1,2를 연달아 풀어보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BOJ 11280 코드를 그대로 들고오는 방법도 있지만, 충분히 O(2^N * M)로도 풀린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11. BOJ 11278 : 2-SAT-2 - S1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforcing 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시리즈가 있어서 1,2를 연달아 풀어보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BOJ 11281 코드를 그대로 들고오는 방법도 있지만, 충분히 O(2^N * M)로도 풀린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BOJ 11280 과 11281은 난이도 차이가 있을 여지가 존재하지만, 11277과 11278은 Bruteforcing으로 풀다보니 답도 바로 나와서 사실상 차이가 없는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12. BOJ 28238 : 정보 선생님의 야망 - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforcing 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;O(5C2 * N)으로도 충분히 풀리는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;딱히 뭔가 특별한게 없던 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/85</guid>
      <comments>https://jun9985.tistory.com/85#entry85comment</comments>
      <pubDate>Mon, 18 Mar 2024 01:14:51 +0900</pubDate>
    </item>
    <item>
      <title>[Lumine] #0 - 시작</title>
      <link>https://jun9985.tistory.com/84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;드디어... 제가 작년 12월부터 진행하기 시작한 프로젝트 관련해서 이야기를 할 수 있게 되었네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에 Pyodide 관련된 글을 올리면서 친한 동생이랑 프로젝트를 시작했다고 한 적이 있습니다. 그때는 뭔가 보여줄 수 있는게 아무것도 없었기도 했어서 어떤 프로젝트인지는 설명을 하지 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 3월에 들어가면서 1차 목표를 달성하고 github 페이지까지 생성해서 사람들이 볼 수 있게 되어 이제 글을 써보고자 합니다. 모델 아키텍쳐 도식을 PyTorch 코드로 실제화 시켜주는 프로젝트 'Lumine'을 소개합니다! 저는 이 프로젝트에서 알고리즘 + 파싱 로직을 주로 맡았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;어떻게 이 프로젝트를 시작하게 되었는가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트는 작년 8월 쯤부터 저 혼자서 구상하고 있었던 프로젝트였습니다. 당시에 저는 PS를 열심히 하면서 그래프 알고리즘에 재미를 느끼고 있었는데요. 그러면서 제가 졸업반인 만큼 &quot;휴학하면서 하고있는 PS 공부가 코딩테스트/대회 결과 등이 아닌 실제 아웃풋으로도 이어질 수 있을까?&quot; 이러한 의문이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면서 저는 그래프 알고리즘이 여러 분야에 적용하기 매우 좋다고 판단해서 이를 실생활 어디에 접목을 할 수 있는지를 생각해보았습니다. 그러다가 예전에 제가 학부연구생 시절이 기억이 났습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 학부연구생 시절에 인공지능 관련해서 교수님 밑에서 프로젝트도 하면서 공부했었습니다. AI 관련 프로젝트를 하다보니 논문은 필연적으로 읽게되는데, 저는 AI 분야에선 모델 아키텍쳐는 주로 그래프 형태로 도식화를 해서 표현하는 걸 배웠습니다. 다만 제가 공부했을 당시에는 (Tensorflow 한정으로)코드를 기반으로 그래프를 그려주는 기술은 존재했지만, 역으로 그래프를 그리면 모델 아키텍쳐 코드로 옮겨주는 기술이나 프로그램은 찾을 수 없었습니다. 그래서 프로젝트를 진행했을 때에는 모델 아키텍쳐 코드를 따로 짜고, 나중에 논문을 작성할 때에는 해당 코드를 그래프 형태로 시각화하는 과정을 번거롭게 거쳐야 했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데, 생각을 해보니 모델 아키텍쳐 그래프가 주어지면 이를 파싱하여 PyTorch 코드로 옮기는 작업은 그래프 알고리즘으로도 충분히 해결될 수 있을 것 같았습니다. 생각을 해보면, 아무리 모델 아키텍쳐 내에서 recursive 구조를 갖는 부분이 있다고 하더라도, 전부 펴보면 모델 아키텍쳐는 일종의 DAG(Directed Acyclic Graph)로 표현이 됩니다. 그래서 모델내에 변수를 forward 하는 순서는 그냥 Topological sort를 돌리는 순서대로 진행하면 될 것 같았습니다. Constructor 메소드 내에는 아키텍쳐에서 언급된 노드들을 전부 기록하면 될 것 같았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;그런데 왜 이렇게 늦어졌는가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 사고 과정을 통해서 그래프 알고리즘을 활용한 프로젝트 아이디어와 제일 중요한 핵심 로직 구현 방법은 어느 정도 생각해두었습니다. 그렇지만 문제가 있었습니다. 바로... 제가 웹에 대해서 하나도 모른다는 점이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무리 생각을 해도 결국에는 서로 모델 그래프를 공유하고 이를 코드로 바꾸는 서비스는 웹 환경에서 제공하는게 제일 깔끔하다는 결론이 나왔습니다. 그렇다면 아무래도 프론트와 백도 구현을 해야한다고 생각을 했었는데, 저는 프론트 / 백 둘다 할 줄 몰라서 혼자서 프로젝트를 할려면 혼자서 둘 다 공부를 해야하는 상황이었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설상가상으로 8~10월에는 삼성 DX 알고리즘 특강도 있었고, 제 2회 보라매컵 예선 및 본선 문제 출제도 해야했어서 웹을 공부할 수 있는 시간이 안 났었습니다. 그래서 저는 일단 프로젝트 개요와 단계별 목표만 어느정도 짜두고, 프로젝트 내의 핵심 로직을 파이썬으로 구현해서 로직이 통하긴 하는가를 테스트 해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 1단계 목표로 생각해둔 범위 내에서는 핵심 로직이 BFS 만으로도 가능하기에 BFS로 구현했고, 어떤 부분들을 노드로써 기록하고 노드 내에는 어느 정보가 담길 것인지는 대충 생각해서 노드를 구성하였습니다. 그러더니 핵심 로직 함수가 정상적으로 PyTorch 아키텍쳐 코드를 뱉어냈습니다. 실제로 Google Colab에 제 함수가 그래프 구조를 파싱하여 생성한 코드를 복붙하고 input을 넣어보니 정상적으로 output까지 뱉어내는 걸 확인하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 로직 코드가 돌아가는 것을 확인했으니... 이제 1단계 목표를 저 혼자 달성하기 위해서는 웹을 공부해야했습니다. 그래서 대강 Vue + Django로 프론트와 백을 정하고 공부할려 했는데 모르는게 너무 많고 공부할 양도 너무 많아 계속 미뤄두었습니다. 그러다가 12월에 이 프로젝트를 같이 하고 있는 동생으로부터 갑자기 연락이 왔습니다. 그래서 카톡을 하던 도중에 그 친구가 웹을 하는 것을 기억해서 &quot;이러한 프로젝트가 있는데~ 웹 부분으로 너가 참여할래?&quot; 이런 톡을 보냈고, 그 친구도 관심이 있다는 표현을 하였습니다. 그래서 12월 말에 디코로 만나서 첫 미팅을 가지기로 하였습니다.&lt;/p&gt;</description>
      <category>CS/Lumine 개발기</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/84</guid>
      <comments>https://jun9985.tistory.com/84#entry84comment</comments>
      <pubDate>Thu, 14 Mar 2024 21:21:30 +0900</pubDate>
    </item>
    <item>
      <title>2024.03.04. ~ 2024.03.10.</title>
      <link>https://jun9985.tistory.com/83</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 24 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 31503 : DP (Large) - P5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;O(NlogN) LIS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 해석해보면 결국 특정 위치의 원소가 꼭 들어갈 때의 LIS의 길이 구하기 문제가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i 번째 원소를 포함한 LIS의 길이는 (i 번째 원소가 마지막 원소인 LIS의 길이) + (i 번째 원소가 제일 처음에 들어있는 LIS의 길이) - 1 이 되는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 배열의 원소들에 -1를 곱하고 역으로 뒤집으면&amp;nbsp; &quot;N번째 원소부터 볼 때 i 번째 원소가 제일 마지막 원소인 LIS의 길이&quot; =&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;i 번째 원소가 제일 처음에 들어있는 LIS의 길이&quot;가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;따라서, O(NlogN) LIS로 먼저 &quot;&lt;span&gt;&amp;nbsp;&lt;/span&gt;i 번째 원소가 마지막 원소인 LIS의 길이&quot;를 모든 i 번째 원소에 대해서 미리 계산하고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열에 모두 -1를 곱하고 뒤집어 또 O(NlogN) LIS로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;N번째 원소부터 볼 때 i 번째 원소가 제일 마지막 원소인 LIS의 길이&quot;를 구한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 각 쿼리 별로 미리 계산해 둔 결과값을 가져다가 쓰면 되므로 총 시간복잡도는 O(NlogN + Q)가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜인지 모르게 BOJ 11045가 생각나는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(사실 Softeer에서 O(NlogN) LIS 버젼의 가장 긴 바이토닉 수열 찾기 문제가 있었는데, 그게 더 비슷한것 같다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 31501 : DP (Small) - G3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP (O(N^2) LIS) 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 문제의 Small 버젼이라 Large 버젼의 AC 코드를 그대로 내서 풀었지만, O(NlogN) LIS 부분을 O(N^2)으로 구해도 되는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 문제는 BOJ 11045가 생각만 나는 문제였다면, 이 문제 같은 경우에는 아에 BOJ 11045의 아이디어를 좀만 꼬아서 낸 문제 같아 G3를 주긴 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 31476 : :blob_twintail_thinking: - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DFS + BFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양갈래 블롭은 {현재 탐색하고 있는 노드, 갈라진 횟수}를 BFS로 넘기면서 쉽게 구현이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS를 하면서 탐색 가능한 노드의 개수를 세고 이를 포니테일 블롭들의 탐색 방법인 DFS를 하면서 현재 몇 개의 노드를 탐색했는지 확인할 때 활용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 전부 탐색했으면 그 때 기준으로만 포니테일의 탐색 시간을 기록하고, 나중에 DFS가 끝나면 서로 비교하는 방법으로 구현하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지문에서 입구의 노드 번호가 1인 것 등 정확히 명시해주었으면 하는 부분들이 있었던 아쉬운 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 31477 : 양갈래 구하기 - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DFS + Tree DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간선의 개수가 N-1개이므로 트리임은 명확하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[i]를 'i번째 노드 밑의 리프 노드들과 연결이 끊어질려면 필요한 최소 비용'이라고 정의하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i번째 노드 밑의 자식의 노드 번호를 j, i번째 노드와 j번째 사이 간선의 비용을 E[i][j] 라고 한다면 dp[i] = sum(E[i][j], dp[j])가 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 DFS를 돌리면서 DP 테이블을 채우고 dp[1]을 출력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;난이도는 G3으로 기여했는데, 이유는 아래 문제와 난이도가 사실상 동일하다고 판단했기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 12784 : 인하니카 공화국 - G3&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DFS + Tree DP 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 문제랑 사실상 동일한 문제다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다만, 트리임을 명시하는게 'N-1개의 간선이 있다.' -&amp;gt; '최소한의 간선으로 모든 노드간의 이동이 가능하도록 그래프를 설계하였다.' 이게 좀 다른데...&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;별 차이가 없는 것 같아서 위 문제도 G3, 이 문제도 G3으로 기여하였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;6. BOJ 30599 : Divisibility Trick - G5&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Ad hoc + Constructive + Math 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;d를 d번 이어서 적는다면 각 자리 수는 d번씩 나오기 때문에 d의 배수가 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;d가 최대 1000인데, 1000을 1000번 적으면 딱 10^6자리 수가 나와서 괜찮다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;7. BOJ 31478 : 포니 양은 놀고 싶어! - G1&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Number Theory + FLT + Modular Inverse + Exponential with DnC 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;FLT의 a ^ {p-1} mod p = 1 이라는 성질을 활용하면...&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;A^{B^C} mod 7 = A^{ a * (7-1) + b } = A^b 이러한 식으로도 정리가 되므로 B^C mod 6 = b 이니 이를 분할정복을 활용해서 O(logC)만에 계산하면 된다. 이후 A^b는 사실 b가 작아서 O(b)도 괜찮지만 그냥 O(logb)로도 계산해도 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;B^C / A 는 그냥 그대로 B^C mod 7을 또 분할정복을 활용해서 계산하고, A ^ 5 mod 7로 모듈로 역원 계산을 해주어 곱해주면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;8. BOJ 31502 : 만화에서 나오는 거 따라하고 그러면 안 된다 - G2&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Dijkstra + BFS 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BFS를 C 기준으로 돌려서 B에서 다시 역추적해서 경로를 파악한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이후에, A 기준으로 Dijkstra를 돌려서 경로에 있는 모든 노드들에 대해서 최단거리를 파악해보면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;B -&amp;gt; C 로 BFS 한 다음 C에서 역추적한다고 계속 틀렸었는데, C부터 역추적 한다면 B에서 C로 갈 때 항상 간선들이 제일 많은 노드로 가는 건 아니니깐... 그걸 나중에 알고 허탈했었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 문제를 사람들이 많이 안 풀었는데, 당시 풀었을 때는 G1로 기여해서 G1가 되었으나 나중에 생각이 바뀌어 다시 G2로 기여하니 G2가 되었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;9. BOJ 6118 : 숨바꼭질 - S1&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BFS 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;각 노드별로 최단거리 파악 + 그 중에서 최장거리인 노드 개수, 최장거리, 제일 작은 노드 번호 찾기.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리 어렵지 않은데... 이게 왜 S1?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단, BFS 기본 문제가 S2~S3 같아서 S2로 기여했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;10. BOJ 16456 : 하와와 대학생쨩 하와이로 가는 거시와요~ - S1&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DP + 약간의 관찰 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;모든 칸을 한 번씩만 지나갈려면, 2칸을 건넌 상태에서 다음에 해야할 행동은 뒤로 1칸 가는 게 고정됨을 알 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 뒤로 1칸 가는 행동의 다음 행동은 항상 또 2칸을 건너는 행동으로 고정됨을 알 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 결과적으로는 2칸을 건넜다면 다음에는 꼭 1칸만 뛸 수 있다고 생각해도 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 DP table을 dp[0][i]를 마지막에 1칸 뛰는 방법으로 i칸에 도착한 방법의 개수, dp[1][i]를 마지막에 2칸 뛰는 방법으로 i칸에 도착한 방법의 개수라고 하면...&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;dp[0][i] = dp[1][i-1] + dp[0][i-1], dp[1][i] = dp[0][i-2]로 점화식을 세울 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;근데 여기서, dp[1][i-1] = dp[0][i-3]은 결국 dp[0][i]에 더 해지는 것을 파악하면 또 DP 테이블을 1차원으로 줄일 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DP식 최적화가 가능한게 뭔가 마음에 든 문제였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;11. BOJ 31497 : 생일 축하합니다~ - B2&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Implementation + Ad hoc 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그냥 각 사람별로 2번씩 물어보면 된다. 두 번 다 맞다는 말이 나오면 해당 사람이 생일이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그런 경우가 없었으면 한 번만 맞다는 말이 나온 사람이 생일이 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;12. BOJ 24417 : 알고리즘 수업 - 피보나치 수 2 - S4&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;나는 DnC (Squaring) + Math 문제로 풀었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1도 풀었는데, 1과는 다르게 N의 범위가 2*10^8까지 가능해서 코드1의 실행 횟수에는 뭔가 패턴이 있다는 판단을 하였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 대강 대입해보니 이게 또 피보나치 수를 이루는 것을 알았다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;매우 큰 N에 대해서 N번째 피보나치 수는 당연히 분할정복을 활용한 거듭제곱으로 행렬 계산을 하니까 그렇게 풀었는데...&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이게 난이도가 S4로 측정되어 다른 풀이 방법이 있나 싶었다. (기본이 그래도 골드 중위권일텐데...)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기여창을 보니 C++로는 O(N) dp도 통과한다고 해서 다시 풀어보니 한 600~700 ms 사이로 통과했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 붙은 태그는 Math + DP인데... 아마 원작자의 의도는 내 풀이였을 것 같다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;13. BOJ 25418 : 정수 a를 k로 만들기 - S3&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BFS 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;사실상 숨바꼭질 시리즈랑 비슷하게 풀 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;14. BOJ 2003 : 수들의 합 2 - S4&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;나는 Prefix Sum + Hash map으로 풀었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;P[i]를 A[1] + ... + A[i]로 두었을 때, A[i]가 마지막 원소로 존재하는 연속된 수열 중 수열의 합이 M인 개수는 j &amp;lt; i 인 P[j] 중&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;P[j] = P[i]-M을 만족하는 결과가 몇 개인지를 세어보면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이를 Hash map으로 관리하여 각 값이 몇 번씩 나오는지를 세어보게 하면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;근데 정해는 그냥 모든 구간에 대해서 브포를 돌리는거라고 한다. (애매할 것 같아서 안 했는데...)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;15. BOJ 13156 : Selling CPUs - G5&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DP 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제 상황을 보고 State를 정하는 작업을 하였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;State : DP[i][j] = i번째 상인까지 총 j개를 팔았을 때의 최대 이득&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;점화식 : DP[i][j] = max(DP[i-1][j-k] + p[i][k]) (0 &amp;lt;= k &amp;lt;= j)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러면 총 시간복잡도 O(MN^2)으로 DP식을 돌려서 풀 수 있었다. 푸는데 한 13분 정도 걸렸다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;슬슬 DP랑 Greedy 연습도 시작해야지.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;16. BOJ 26607 : 시로코와 은행털기 - G3&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Knapsack DP 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;a+b = x 는 고정이므로 k개의 ai의 합을 M이라고 하면 M * (kx - M) 이런 꼴을 우리는 최적화 하려는 걸 알 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러면 dp식을 아래와 같이 세우면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;State : dp[i][j] = i명의 사람의 a의 합이 j인지 가능한가?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;점화식 : dp[i][j] = dp[i-1][j-p[l]] || dp[i][j] // l번째 사람까지 보았을 때...&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 나중에 dp[k][j] = 1인 j들을 보고 j * (kx-j)를 계산하여 그 중 최댓값을 구하면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(사실 kx/2에 제일 가까운 j를 찾아서 구해도 되기는 하는데... 그러면 이분탐색을 해야하니 좀 더 번거롭긴하다.)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DP 연습을 확실히 많이 해야겠다는 생각이 들었던 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;17 ~ 18. [제4회 고려대학교 MatKor Cup : 2024 Winter/Spring Open Contest] - (Solved : 2 / 15) : 배경 조건만 맞추었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;17. BOJ 31533 : Furiosa AI 영상 처리 가속 - B2&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Math + Case-working .문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단 확실한 건 Renegade를 한 컴퓨터에 바르면 해당 컴퓨터는 일하는 속도가 더 빨라진다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러므로 Renegade를 특정 컴퓨터에 발랐을 때, 해당 컴퓨터에 두 개의 일을 모두 주는 경우랑 하나하나 나눴을 때 경우의 시간을 모두 계산하여 그 중 최솟값을 출력하면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;18. BOJ 31534 : 현대모비스 선풍기 굴리기 - S5&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Math + Geometry 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기하 문제라서 아래와 같이 그려서 설명해야할 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;421&quot; data-origin-height=&quot;334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfC5uE/btsFFKJLQdw/ztgjTpLIjTkQLRJ39AkFmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfC5uE/btsFFKJLQdw/ztgjTpLIjTkQLRJ39AkFmK/img.png&quot; data-alt=&quot;a,b,h는 문제에서 나온 변수고, 나머지는 임의로 내가 지은 것임.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfC5uE/btsFFKJLQdw/ztgjTpLIjTkQLRJ39AkFmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfC5uE%2FbtsFFKJLQdw%2FztgjTpLIjTkQLRJ39AkFmK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;237&quot; height=&quot;334&quot; data-origin-width=&quot;421&quot; data-origin-height=&quot;334&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;a,b,h는 문제에서 나온 변수고, 나머지는 임의로 내가 지은 것임.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러면 그리는 자취의 넓이는 ((c+d) ^ 2 - c ^ 2) * phi 가된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;h2 = h * a / (b-a), c ^ 2 = h2 ^ 2+ a ^ 2, (c+d) ^ 2 = (h2+h) ^ 2 + b ^ 2 이므로 이를 대입해서 계산하면 되는데,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;b = a 면 아에 원통 모양이라서 자취가 무한하게 남으니 -1를 출력해주어야 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 혹시나 몰라서 나는 a &amp;gt; b이면 swap(a,b)를 해주긴 했다. (어차피 뒤집어서 굴려도 같은 넓이가 나오니깐)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;19. BOJ 1275 : 커피숍2 - G1&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Segment Tree 문제.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;사실상 Segment Tree 기본문제였다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;수열과 쿼리 문제와 다른 점은 한 쿼리에 합 쿼리 + 업데이트 쿼리가 같이 들어오는 정도였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;20~24. [2024 상반기 전남대학교 PIMM 알고리즘 파티] - (Solved : 5 / 9) : 끝나기 1시간 전부터 풀기 시작했다. 1시간만에 5솔 정도에 모두 1트 AC받아서 기분이 너무 좋았다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;20. BOJ 31561 : 시계탑 - B4&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Math 문제였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그냥 처음 30분은 나누기 2를 한 결과를 더하고, 30분이 넘어가는 시점부터 남은 30분에서는 3/2를 곱하면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;21. BOJ 31562 : 전주 듣고 노래 맞히기 - B1&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Implementation + Hash map 문제였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여러 구현 방법이 있겠지만 나는 key : 첫 세 음, value : 노래 제목 이렇게 넣었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러면서 만약에 key가 중복되면 value를 ?로 바꿔서 중복 체크를 하였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;22. BOJ 31563 : 수열 회전과 쿼리 - S2&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Math + Prefix Sum 문제였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;상대적인 위치가 변하지 않으니 첫 번째 element의 위치가 어느 위치로 변하는 지만 기록해도 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이후에 Prefix Sum을 할 때 역으로 각 원소들의 처음 위치를 계산하여 알맞게 Prefix Sum 결과를 더하면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;23. BOJ 31564 : 육각타일미로 탈출기 - S1&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BFS 문제였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기본적인 BFS 문제인데, 그냥 y와 x의 변화량이 y가 짝/홀일 때 바뀌는 정도?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Implementation에 좀 더 비중을 둔 문제 같았다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;24. BOJ 31566 : 힘세고 강한 아침 - G2&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Floyd-Warshall 문제였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제 설명만 보면 결국 특정 노드를 지나지 않고 최단거리 찾는 건데...&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그냥 N이 작아서 각 노드별로 해당 노드를 지나지 않고 플로이드-워셜을 돌리고, 쿼리별로 O(1)로 대답을 해주면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;총 시간복잡도는 O(N^4 + Q)인데, 오프라인 쿼리를 쓴다면 O(N^4 + QlogQ)가 되긴 할 거다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(오프라인 쿼리를 쓴다면 필요없는 계산은 더 줄일 수 있어서 좀 더 빠르긴 하다. 그렇지만... 굳이?)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러고보니 지난주부턴가 이번주 부턴가 이제 브론즈는 대회 문제 아니고서는 기록하지 않기로 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/83</guid>
      <comments>https://jun9985.tistory.com/83#entry83comment</comments>
      <pubDate>Wed, 13 Mar 2024 02:25:18 +0900</pubDate>
    </item>
    <item>
      <title>2024.02.26. ~ 2024.03.03.</title>
      <link>https://jun9985.tistory.com/82</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 18문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 13511 : 트리와 쿼리 2 - P3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LCA, Sparse Table 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 아무 노드를 루트로 두어 LCA Table + 루트로부터 해당 노드까지 가는데의 비용을 O(NlogN)으로 다 계산한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이제 각 쿼리에서의 u,v에 대한 LCA를 lca라고 한다면...&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1번 쿼리는 루트에서의 u까지의 비용 + v까지의 비용 - 2 * lca까지의 비용 이렇게 계산하면 된다.&lt;/li&gt;
&lt;li&gt;2번 쿼리는 만약에 k가 u에서 lca까지의 거리보다 크다면 역으로 v에서부터 lca까지 가는 도중에 (u에서 v까지 거치는 노드 개수) - k 번째 노드를 아니면 u에서 lca까지의 k번째 노드를 LCA Table로 O(logN)에 구하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 시간복잡도는 O((N+Q)logN).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하필 이 문제 제출하자마자 백준 서버가 터졌어서 한 번 제출할때마다 결과를 보기까지 15분 정도 걸렸었다. (그 와중에 3 WA를 적립했어서 AC까지 1시간 걸렸음;;;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 17479 : 정식당 - S3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Hash set 문제.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 구현 방법이 있을 것 같은데, 나는 그냥 hash map으로 메뉴 이름 주면 {종류, 가격} 이렇게 담았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러고 모든 메뉴를 받아서 이를 {종류, 가격}으로 바꾸고 정렬해서 일반 메뉴들 계산하고 다음에 특별 메뉴들 계산, 마지막에 서비스 계산하도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 11724 : 연결 요소의 개수 - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 DSU로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양방향 간선으로 이루어져 있다면 어느 노드부터 시작해도 연결된 노드들은 다 갈 수 있으니 DFS나 BFS로도 풀 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그게 정해였는데, 나는 귀찮아서 DSU로 풀었다. 그리고 개인적으론 DSU 풀이를 익히는게 나중에 Kruskal Algorithm(MST찾는 알고리즘)처럼 DSU를 활용하는 그래프 알고리즘 및 문제 유형들을 이해하는 데도 좀 더 도움이 된다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[제3회 초콜릿컵] - Solved : 5 / 14 (시작 시간에 점심 먹을 것 같아서 아레나 등록은 안 했다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 31458 : !!초콜릿 중독 주의!! - B2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation 문제.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 팩토리얼 먼저 계산한다 그랬는데, 팩토리얼은 0! = 1, 1! =1 이므로 팩토리얼이 뒤에 하나라도 붙는지만 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;logical not은 개수가지고 짝수면 그대로, 아니면 값을 바꿔주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 31460 : 초콜릿과 11과 팰린드롬 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math + Constructive 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N이 짝수면 그냥 1로 도배해도 괜찮다. (길이가 2k라면, 11이 k번 도배하는걸로 생각하면 되니깐.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 N이 홀수면 케이스를 좀 더 고려해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;N == 1 : 11 * 0 = 0 이므로 0을 출력한다.&lt;/li&gt;
&lt;li&gt;N%4 == 3 : ...1x1... 이러한 형태인데, 앞뒤의 1이 홀수 개수이다. 2를 넣는다면, ...1 121 1... 이런식으로 11의 배수를 만들 수 있다.&lt;/li&gt;
&lt;li&gt;나머지, 그냥 ...101... 이렇게 구성하면 된다. (0 앞뒤의 1의 개수가 짝수이므로 11로 다 묶인다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. BOJ 31459 : 초콜릿과 ㄱ나이트 게임 (Sweet) - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Greedy 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나이트가 하나라도 공격을 하지 못하는 곳에 최대한 배치하는게 최선이라 생각을 했고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나이트의 공격범위가 우측 하단이므로, 우측 하단부터 순서대로 채우는 게 최선일 거라는 판단을 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 Proof by AC인 느낌이라 매우 짜치는 것 같아서 나중에 에디토리얼을 봐야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ 31462 : 삼각 초콜릿 포장 (Sweet) - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation+Greedy 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 위부터 맞게 되었는지 순차적으로 확인하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 R를 처음에 찾았으면 우측 하단과 좌측 하단이 R인지 확인, B를 찾았으면 우측과 우측 하단이 B인지 확인하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인을 했으면 다른 값으로 바꿔서 중복으로 확인하지 않도록 구현했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. BOJ 31464 : 초콜릿 괴도 코코 (Sweet) - G2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Bruteforcing + BFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관찰을 했을 때, 하나로 이어져 있지만 어느 점이든 단절점이 될 수 있는 형태의 그래프는 트리라는 결론을 내렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 모든 가능한 점에 대해서 먼저 없애고, 이후에 남은 연결요소의 개수가 1개이면서, 트리 형태인지를 확인하였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리 형태를 확인하는 것은 어느 점이든 루트로 두었을 때 사이클만 생기지 않으면 되므로 BFS 시간복잡도인 O(N^2)만에 가능했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 총 시간복잡도는 O(N^4)인데, 구현량이 매우 많았어서... Implementation 문제라고도 생각된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. BOJ 17087 : 숨바꼭질 6 - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Number Theory 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각해보면 +-D로 갈 수 있는 위치들은 전부 S + kD라는 형태로 표현이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, Ai = S+kD이므로 S-Ai는 D의 배수라는 의미이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이말은 즉슨, |S-A1|, |S-A2|....의 공약수만 D가 될 수 있는데, D가 최대일려면 이 중에서 최대공약수를 찾으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;__gcd 함수를 사용해서 쉽게 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10. BOJ 27907 : The primes contain arbitrarily long arithmetic progressions - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ad hoc + Constructive + Math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지문 논문 관련 이야기는 그냥 '이러이러한 일이 있었다~' 수준이었고 결국에 구해야하는 건 특정 길이 n의 소수로만 이루어진 등차수열이었다. 그런데 문제에서 수를 중복해서 넣으면 안 된다는 말이 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 공차가 0도 가능하므로 특정 소수를 n번 출력하면 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11. BOJ 31499 : 프랙탈 수열 - S3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ad hoc + Combinatorics + Math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;A의 정의를 보았을 때 모두 서로 다른 양의 값이라서 B의 원소들도 양수일 것인데, C에 0이 들어가 있으면 B = C가 불가능 하다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;따라서 B = C를 만족할려면 B의 모든 원소들은 1 ~ N 사이의 값을 가지고 있어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;그런데, A는 서로 다른 N개의 양의 정수들로 구성되어 있다고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;따라서, A는 1~N까지 모든 정수가 들어있는 순열이 되어야 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;그렇다면 A가 어떤 순서로 배치되어 있든 B는 항상 정렬된 결과 = {1,2,3,....,N}이 되며, B_i = i 이므로 B_{B_i} = B_i = C_i를 만족하니 A가 프랙탈 수열인 경우의 수는 N!이 된다.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에도 Bronze 7 문제를 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Programmers 2 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. [2024 KAKAO WINTER INTERNSHIP] 가장 많이 받은 선물 - Lv.1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Simulation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 이름을 index로 mapping하여 2D matrix를 만든다. (a[i][j] -&amp;gt; i번째 사람이 j번째 사람에게 선물을 준 횟수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면서 gifts 배열을 전부 돌면서 a[i][j] 및 각 사람의 선물 지수도 따로 계산한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 모든 사람들에 대한 짝에 대해서 누가 누구에게 선물을 주는지 계산해보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. [2024 KAKAO WINTER INTERNSHIP] 가장 많이 받은 선물 - Lv.1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관찰 + BFS/DFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관찰을 해보면, 새로 생긴 노드는 in-degree가 0이고, out-degree가 2 이상인 노드가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데, 8자나 도넛 모양에 속하는 노드는 in-degree가 0인 노드가 있을 수 없고, 막대 모양은 out-degree가 1 아니면 0이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 새로 생긴 노드는 그냥 in-degree가 0인 노드들 중에서 out-degree가 2 이상인 노드를 찾으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;찾은 다음에 해당 노드와 이어진 노드들에서 시작해 BFS를 돌리면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탐색할 때 간선들과 노드들의 개수를 기록하면, 8자 / 도넛 / 막대 모양인지도 쉽게 파악이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 막대 모양은 해당 모양에 속한 노드들을 전부 탐색할 수 없는 경우도 있긴 한데, 그래도 막대의 일부도 막대 모양을 지니므로 막대인지 아닌지는 판단할 수 있다. (사실 사이클이 없는 모양은 막대 밖에 없다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관찰이 꽤 재밌었던 문제였다. 코테 문제들에도 이런 관찰을 요구하는 문제가 있어서 놀랐다. (너무 구현 위주라고만 생각했나보다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/82</guid>
      <comments>https://jun9985.tistory.com/82#entry82comment</comments>
      <pubDate>Mon, 4 Mar 2024 14:02:35 +0900</pubDate>
    </item>
    <item>
      <title>Mo's 알고리즘을 내가 이해한 방식대로 설명해보기</title>
      <link>https://jun9985.tistory.com/81</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;지난번에 Dijkstra 알고리즘에 대해서 제가 이해한 방식대로 설명해봤었는데, 이번에는 Mo's 알고리즘을 제가 이해한대로 한 번 설명해보고자 합니다. 물론, 지난번과 같이 이건 제가 이해한대로 설명한 것이기 때문에 정확한 설명이 아닐 수 있습니다. 그래도 Mo's 알고리즘이 무엇인지를 이해하는데에는 도움이 되지 않을까 해서 글을 올려봅니다. 그 전에 Mo's 알고리즘이 무엇인지와 어떤 문제들을 해결할 수 있는지에 대해서 설명해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Mo's 알고리즘은 무엇인가?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;후술하겠지만 Mo's 알고리즘은 &lt;u&gt;&lt;b&gt;Sqrt-Decomposition&lt;/b&gt;&lt;b&gt;(&lt;/b&gt;&lt;b&gt;평방분할)의 아이디어를 차용해서 특이한 구간 쿼리들을 계산하는 테크닉&lt;/b&gt;&lt;/u&gt; 입니다. 구간 쿼리라면 Segment Tree를 주로 떠올리실텐데, 이 알고리즘의 시간복잡도는 Segment Tree보다 느리고 주로 업데이트 쿼리가 없는 경우에만 사용할 수 있습니다. (저는 잘 모르지만 &lt;a href=&quot;https://codeforces.com/blog/entry/72690&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이런 글&lt;/a&gt;처럼 업데이트 쿼리가 있더라도 사용할 수 있는 경우가 있는 것 같긴 합니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그렇다면 왜 이 알고리즘을 사용하는가? 바로 이 알고리즘은 &lt;u&gt;Segment Tree로는 잘 못 푸는 유형들의 쿼리를 해결할 수 있기 때문&lt;/u&gt;입니다. 기본 문제들의 쿼리 유형들을 한 번 볼까요?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/13547&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 13547 : 수열과 쿼리 5&lt;/a&gt; - 쿼리 : [l,r] 범위 내에 서로 다른 수들의 개수 구하기&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/13548&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 13548 : 수열과 쿼리 6&lt;/a&gt; - 쿼리 : [l,r] 범위 내에서 가장 많이 등장하는 수의 개수 구하기&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/13546&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 13546 : 수열과 쿼리 4&lt;/a&gt; - 쿼리 : [l,r] 범위 내에서 같은 값의 원소들 중 제일 멀리 떨어진 거리 구하기&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이처럼 구하고자 하는 쿼리들이 매우 특이합니다. 그래서 Segment Tree로는 쿼리 구조를 어떻게 짜야 하는가와 어떤 정보들을 각 노드에 저장해야 하는지를 떠올리기 매우 어렵습니다. 그런데 이번에 다룰 Mo's 알고리즘은 이를 해결할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Mo's 알고리즘에 대한 설명&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;제가 위에서 Mo's 알고리즘을 활용하는 문제들을 설명했지만 난이도가 매우 높습니다. 그래서 구간 쿼리 입문용 문제를 들고와서 이걸로 설명해보겠습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11659&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 11659 : 구간 합 구하기 4&lt;/a&gt; - 쿼리 : [l,r] 범위의 모든 원소들의 합 구하기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;물론 이 문제의 정해는 Prefix Sum을 활용해서 O(N+Q)가 정해긴 하지만, 업데이트 쿼리가 없으면서도 구하고자 하는 쿼리가 매우 간단한지라 이 문제로 설명해보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;우선, 예제로 설명하긴 너무 작으니 데이터를 좀 더 늘려볼까요?&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708871603803&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;9 9
1 2 3 4 5 6 7 8 9
2 4
3 7
1 5
1 2
2 7
7 9
8 8
5 8
6 7&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 정도면 충분할 것 같습니다. 이제 이 예제 가지고 설명해보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;일단 Mo's 알고리즘의 아이디어는 &lt;u&gt;&lt;b&gt;&quot;쿼리들을 어떻게 효율적인 순서로 배치해서 다음 쿼리를 계산할 때 지금 계산한 쿼리 값을 재활용 할 수 있지 않을까?&quot;&lt;/b&gt;&lt;/u&gt; 에서 시작합니다. 지금 예제 데이터만 보더라도 만약에 우리가 5번째 쿼리([2,7])를 처리하고 2번째 쿼리([3,7])를 처리한다면 5번째 쿼리 값에서 2번째 element를 값을 빼는 것만으로도 2번째 쿼리에 대한 답을 찾을 수 있겠죠?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그러면 쿼리 순서를 어떻게 하면 잘 정리할 수 있을까요? 일단 &lt;u&gt;각 쿼리를 [s,e]로 시작점이 s, 끝점이 e라 표현&lt;/u&gt;하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그러면 &lt;u&gt;&lt;b&gt;s가 동일한 쿼리는 e가 작은 순서대로 처리하면 시작점이 s인 모든 쿼리에 대해서 O(N)만에 구할 수 있습니다&lt;/b&gt;&lt;/u&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그렇다면 쿼리들을 [s,e] 순서대로 정렬해봅시다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708872282348&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 쿼리들을 [s,e]로 정렬한 결과
1. [1,2]
2. [1,5]
3. [2,4]
4. [2,7]
5. [3,7]
6. [5,8]
7. [6,7]
8. [7,9]
9. [8,8]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이렇게 처리한다면 시간복잡도는 어떻게 될까요? 우선 시간복잡도 설명이 길어질 것 같으니 몇 개의 기호를 미리 정하고 생각해봅시다. 아래와 같이 정의하면서 설명해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;O(A) =&lt;/b&gt; &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;전의 쿼리의 s와 현재 쿼리의 s가 동일할 시에 생기는 비용&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;O(B) = 전의 쿼리의 s와 현재 쿼리의 s가 차이가 날 시에 생기는 비용&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;O(C) = 전의 쿼리의 e와 현재 쿼리의 e가 차이가 날 시에 생기는 비용&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;O(T(n)) = 전의 쿼리의 s나 e를 현재 쿼리 s와 e에 맞출려고 한 칸 움직일 때에 드는 비용&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이렇게 정의를 해둔다면 모든 쿼리를 처리하는 데 총 시간복잡도는 &lt;b&gt;O(Q * (A + B + C) * T(n))&lt;/b&gt; 이 됩니다. 예제 문제에서 O(T(n))은 s나 e가 한 칸 움직일 때 해당 element를 지우거나 더하면 되니 O(1)로 계산이 됩니다. 그래서 시간복잡도 분석은 O(Q * (A + B + C))만 고려하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;일단 &lt;b&gt;O(&lt;b&gt;&lt;b&gt;Q * (B&lt;/b&gt; +&lt;/b&gt;&amp;nbsp;C)) &lt;/b&gt;에 대해서 먼저 알아보도록 하겠습니다. e는 쿼리에 등장하는 각 s에 대해서 최대 N번씩 옮깁니다. 또한, 쿼리가 s를 기준으로 정렬이 되어있으므로 s는 최대 N번 움직입니다.&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;그러면&amp;nbsp;&lt;/span&gt;&lt;b&gt; O(&lt;b&gt;&lt;b&gt;&lt;b&gt;Q * B) &lt;/b&gt;+&lt;/b&gt;&lt;/b&gt; O(Q * C) &lt;b&gt;=&amp;nbsp; &lt;b&gt;O(&lt;span&gt;s가 움직이는 최대 횟수)&lt;/span&gt;&lt;b&gt;&lt;b&gt;&amp;nbsp;+&lt;/b&gt;&lt;/b&gt;&lt;span&gt; O(e가 움직이는 최대 횟수) = O(N&lt;/span&gt;) + O(N^2)&lt;/b&gt;&amp;nbsp;= O(N^2&lt;/b&gt;)&lt;/b&gt; 이라는 결과가 나옵니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;O(Q * A)&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;는 딱히 (지금은) 고려하지 않아도 됩니다. 왜냐하면 위에서 &lt;b&gt;O(Q * C&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;span&gt;의 계산을 하면서 s가 동일할 때에 대해서 시간복잡도 계산을 끝냈기 때문입니다. 그래도 각 쿼리들을 살펴보긴 해야하니깐 &lt;b&gt;O(Q)&lt;/b&gt;가 됩니다. 따라서 총 시간복잡도는&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;O(Q+N^2)&lt;/b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333; text-align: start;&quot;&gt;이 됩니다. 이렇게 풀면 당연히 시간초과가 납니다. 좀 더 최적화 할 방법이 없을 까요?&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이렇게 한 번 생각해봅시다. 만약에 &lt;b&gt;쿼리들을 정렬할 때 s의 차이가 별로 안 나는 것들끼리 묶어보면 어떨까요?&lt;/b&gt; s가 1,2인 것끼리 같이, 3,4인 것끼리 같이... 이렇게 2개씩 묶어서 정렬해봅시다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708872967551&quot; class=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;// 새롭게 쿼리들을 정렬한 결과
1. [1,2]
2. [2,4]
3. [1,5]
4. [2,7]
5. [3,7]
6. [6,7]
7. [5,8]
8. [8,8]
9. [7,9]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이렇게 정리하면 시간복잡도가 어떻게 달라질까요? 우선 O(A), O(B)의 정의를 다시 새롭게 해야합니다. 재정의된 O(A), O(B), O(C)는 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;O(A) =&lt;/b&gt; &lt;b&gt;&lt;b&gt;전의 쿼리의 s 묶음과 현재 쿼리의 s 묶음이 동일할 때 생기는 비용&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;O(B) = 전의 쿼리의 s 묶음과 현재 쿼리의 s 묶음이 차이가 날 시에 생기는 비용&lt;/b&gt;&lt;/b&gt;&lt;b&gt;&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이제 다시 &lt;b&gt;O(Q * (A + B + C) * T(n))&lt;/b&gt;을 계산해보겠습니다. &lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;우선 우리는 이제 &lt;b&gt;O(Q * A)&lt;/b&gt;도 분석해보아야 합니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt; 왜냐면 이제 &lt;b&gt;&lt;u&gt;현재 쿼리의 s 묶음이 전의 쿼리의 s묶음과 동일하더라도, s값 자체에는 차이가 있을 수가 있습니다.&lt;/u&gt;&lt;/b&gt; 다만, 다르더라도 실제로 최대 움직이는 횟수는 1칸이므로 O(Q*A)는 &lt;b&gt;O(Q)&lt;/b&gt;가 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333; text-align: start;&quot;&gt;이제 뒤에 &lt;b&gt;O(&lt;b&gt;&lt;b&gt;Q * B)&lt;/b&gt;&amp;nbsp;+&lt;/b&gt;&lt;span&gt; O(&lt;/span&gt;Q * C)&lt;/b&gt;도 바뀌는데, 쿼리는 이제 &lt;u&gt;s묶음을 기준으로 정렬&lt;/u&gt;이 되어있습니다. s 묶음의 크기는 2이므로 따라서, &lt;u&gt;s의 묶음은 최대 N/2번 달라지게 됩니다.&lt;/u&gt; 그래서, &lt;b&gt;O(Q * B) = O(N / 2)&lt;/b&gt;가 됩니다. 그리고 이제 &lt;u&gt;e는 각 s의 묶음 별로 최대 N번&lt;/u&gt; 움직이기 때문에, &lt;b&gt;O(Q * C) = O(N * (N / 2)) = O(N^2 / 2)&lt;/b&gt;가 됩니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 총 시간복잡도는 &lt;b&gt;O(Q) + O(N / 2) + O(N^2 / 2) = O(Q + N^2 / 2)&lt;/b&gt;로 바뀝니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이러한 패턴을 알았으면 눈치채셨을 겁니다. 우리가&lt;u&gt;&lt;b&gt; 쿼리 내에 s를 K개씩 한 묶음으로 묶고 정렬을 한다면 총 시간복잡도는&lt;/b&gt; &lt;b&gt;O(K*Q+N^2/K)&lt;/b&gt;&lt;/u&gt;라는 결과가 나옵니다! 그러면 이 식을 어디까지 최적화 할 수 있을 까요? 바로 &lt;u&gt;&lt;b&gt;K = sqrt(N)으로 두면 최적화&lt;/b&gt;&lt;/u&gt;가 됩니다. K = sqrt(N)이라 두면 &lt;u&gt;&lt;b&gt;총 시간복잡도는 O((Q+N) * sqrt(N) * T(n)) = O(&lt;u&gt;&lt;b&gt;(Q+N) * sqrt(N)&lt;/b&gt;&lt;/u&gt;)&lt;/b&gt;&lt;/u&gt;이 됩니다.&amp;nbsp; 여기서 K = sqrt(N) 아이디어는 Sqrt-Decomposition 아이디어랑 비슷하죠?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 실제로 Mo's 알고리즘은 위에서 쿼리들의 순서들을 재배치하는 Offline-Query 테크닉을 사용하는데, &lt;b&gt;[floor(s/sqrt(N)), e]를 기준으로 정렬&lt;/b&gt;해서 풉니다. 다만, &lt;b&gt;sqrt(N)은 Sqrt-Decomposition 알고리즘 처럼 사실 정확하게 sqrt(N)로 둘 필요는 없고 적당한 크기로 지정해주어도 됩니다.&lt;/b&gt; 그리고 구현 팁이라면 범위를 늘리는 순서를 먼저 실행하고 이를 줄이는 방향으로 구현하는 게 더 좋습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;아래 코드는 위의 예제 문제를 Mo's 알고리즘으로 푼 풀이 코드입니다. 생각보다 코드가 간결하죠?&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708874811739&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include&amp;lt;bits/stdc++.h&amp;gt;
#define ll long long

using namespace std;

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    
    ll N, Q;
    cin &amp;gt;&amp;gt; N &amp;gt;&amp;gt; Q;
    
    vector&amp;lt;ll&amp;gt; v(N);
    for(int i =0; i&amp;lt;N; ++i) cin &amp;gt;&amp;gt; v[i];
    
    vector&amp;lt;tuple&amp;lt;ll,ll,ll,ll&amp;gt;&amp;gt; Queries(Q);
    vector&amp;lt;ll&amp;gt; ans(Q);

    for(int i = 0; i &amp;lt; Q; ++i){
        ll s, e;
        cin &amp;gt;&amp;gt; s &amp;gt;&amp;gt; e;
        --s; --e;
        Queries[i] = {s/sqrt(N), e, s, i};     
    }

    sort(Queries.begin(), Queries.end());
    // s/sqrt(N)을 우선적으로 정렬, 같으면 e를 우선적으로 정렬.

    ll curr_ans = 0; // 쿼리에 대한 답 기록용 변수.

    ll sqrt_s, e, s, idx;
    tie(sqrt_s, e, s, idx) = Queries[0];
    for (int i = s; i &amp;lt;= e; ++i){
        curr_ans += v[i];
    }
    ans[idx] = curr_ans;
    /// 첫 쿼리는 O(N)이긴 하지만 총 시간복잡도는 O(N * sqrt(N))이 있어서 무시됩니다.

    for(int i = 1; i &amp;lt; Q; ++i){
        ll sqrt_s, n_e, n_s, idx;
        tie(sqrt_s, n_e, n_s, idx) = Queries[i];

        while(n_s &amp;lt; s) curr_ans += v[--s];
        while(n_e &amp;gt; e) curr_ans += v[++e];
        // 범위 증가
        
        while(n_s &amp;gt; s) curr_ans -= v[s++];
        while(n_e &amp;lt; e) curr_ans -= v[e--];
        // 범위 감소
        
        ans[idx] = curr_ans;
    } 
    
    for(auto answer : ans){
        cout &amp;lt;&amp;lt; answer &amp;lt;&amp;lt;&quot;\n&quot;;
    }
    
    return 0;
} // Offline Query + Mo's Algorithm&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이렇게 오늘 Mo's 알고리즘에 대해서 글을 써봤습니다. 이 알고리즘의 진가는 사실 위에 제가 예시로 든 수열과 쿼리 문제들에서 엄청 느낄 수 있는데, 저는 Segment Tree가 못 푸는 독특한 쿼리들을 풀 수 있다는 점에서 이 알고리즘을 꽤 흥미롭게 공부했었습니다. 제 글을 통해서 이 알고리즘에 대해서 어느 정도 이해하는데 도움이 되셨다면 좋겠습니다 :)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;[참고] - 저는 아래 글들에서 Mo's 알고리즘을 배웠습니다!&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://blog.naver.com/kks227/221401154455&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://blog.naver.com/kks227/221401154455&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://justicehui.github.io/hard-algorithm/2019/06/17/MoAlgorithm/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://justicehui.github.io/hard-algorithm/2019/06/17/MoAlgorithm/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 Sqrt-Decomposition과 Offline Query를 모르는 분들을 위한 간략한 설명&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Sqrt-Decomposition (평방 분할 / 버킷 알고리즘)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N개의 칸을 대강 sqrt(N)개의 칸 씩 한 구간으로 나누어서 처리하는 방법입니다. 그렇다면 총 sqrt(N)개의 구간이 생겨서 구간 쿼리에 대해서 대강 sqrt(N)개의 구간만 보면 됩니다. (여기서 '대강'이라는 수식어를 붙인 이유는 실제 구현시에는 정확히 sqrt(N)이 아니라 적당한 값을 잡아서도 구현하기 때문입니다. 만약에 N = 100'000 일때 sqrt(N)이 316 정도이니 300 정도로 잡아서도 구현해요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구간이 겹치면 O(1)만에 대답, 걸치면 최대 O(sqrt(N))만큼만 보면 되어 각 쿼리별로 O(sqrt(N))만에 대답이 가능합니다. 이렇게 보면 또 Segment Tree 하위 테크닉 같은데... 업데이트가 O(1)인 점이 장점입니다. 또한, Segment Tree로는 안 되지만 이 테크닉으로 풀리는 문제들도 존재합니다. (예 : BOJ 17410, BOJ 13545)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Offline Query&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리의 순서를 재정렬해서 문제를 더 쉽게 푸는 방법론입니다. 구간 쿼리에서 이 테크닉을 사용하는 예시로는 BOJ 16978이 있습니다. 만약에 2번 쿼리에 대해서 k를 오름차순으로 정렬을 해준다면? 1번 쿼리가 총 k번 적용되었을 때 각각 답을 해주기도 편하겠죠? 이런식으로 쿼리의 순서들을 바꿔서 문제를 더 쉽게 풀 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구간 쿼리랑은 주로 Mo's랑 많이 엮입니다. 그런데 이거 외에도 그래프 문제에서도 '간선을 제거하는 쿼리'로 DSU랑 엮어서 같이 나오는 경우도 있습니다. (예 : BOJ 15586, BOJ 12012, BOJ 17398)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/Algorithm</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/81</guid>
      <comments>https://jun9985.tistory.com/81#entry81comment</comments>
      <pubDate>Mon, 26 Feb 2024 00:33:04 +0900</pubDate>
    </item>
    <item>
      <title>2024.02.19. ~ 2024.02.25.</title>
      <link>https://jun9985.tistory.com/80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 13 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 31430 : A+B - 투 스텝 - B1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A + B가 최대 2*10^18까지 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 'a' = 0, 'b' = 1, ... 이렇게 매핑하면 26진법으로 표현이 되면서도 26^13 이 2*10^18보다 더 크므로 26진법 인코딩을 해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 다음 프로그램 에서는 26진법 표현을 받고 이를 다시 10진법으로 변환하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음으로 푼 투 스텝 문제라서 리뷰해보았다. 투 스텝 문제를 이해하고 입문하기 매우 좋은 문제라 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp; BOJ 15651 : N과 M (3) - S3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Backtracking 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 N^M 가지의 경우의 수를 전부 돌려보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 N과 M 문제들과 비슷한 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 5347 : LCM - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Number Theory 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 LCM을 계산해주면 된다. (a*b) / __gcd(a,b);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 1280 : 나무 심기 - P4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Segment Tree 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌표 x에 대해서 좌표 x보다 작은 좌표들에 심겨진 나무들을 l개 있고, 반대로 좌표 x보다 큰 좌표에 심겨진 나무들이 n-r개가 있다고 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 좌표 x보다 작은 좌표에 심겨진 나무들의 좌표들을 x1,x2,...,xl 이라 하고, 좌표 x보다 큰 좌표에 심겨진 나무들의 좌표들을 xr, ... , xn이라고 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 좌표 x에 나무를 심으면 cost는 (xr+...+xn - (n-r)*x) + (l * x - (x1+x2+...+xl))로 계산할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 Segment Tree에 [l,r] 범위에 대해서 각각 {나무의 개수, 나무 좌표값들의 합}를 저장하여 관리한다면 쉽게 답을 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 1244 : 스위치 켜고 끄기 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Simulation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남학생 쿼리에 대해서는 그냥 O(N)으로 구현해도 상관없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여학생 쿼리는 투 포인터로 구현하긴 했지만 N이랑 쿼리 수가 너무 작은 관계로, 그냥 O(N^2)로 구현해도 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. BOJ 1024 : 수열의 합 - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연속된 범위의 수들의 개수가 홀수 개수라면 (중앙값) * (개수)가 N과 같으면 그 부분이 가능한거고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;짝수 개수라면 (중앙의 두 값의 합) * (개수/2)가 N과 같으면 그 부분이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, L부터 100까지 모든 길이에 대해서 길이가 홀수면 N을 나눌 수 있는지 확인하고, 짝수면 2*N을 나눌 수 있는지를 확인하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가능하다면 그 값들을 중심으로 나머지 수들을 채워나가면 되는데, 이건 또 수식으로 잘 정리하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ 15900 : 나무 탈출 - S1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 중간에 트리에서 특정 노드를 골라서 전체를 옮기는 문제면 몰라도...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어차피 한 턴에 말 하나를 부모 노드로 꼭 옮긴다면, 게임은 모든 리프 노드에 대해서 루트까지의 길이의 합만큼의 턴이 지나면 게임이 끝난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 BFS를 활용해서 리프 노드 및 거리들을 파악해 이를 더하면 답을 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에도 Bronze 6 문제를 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/80</guid>
      <comments>https://jun9985.tistory.com/80#entry80comment</comments>
      <pubDate>Sun, 25 Feb 2024 22:39:44 +0900</pubDate>
    </item>
    <item>
      <title>2024.02.12. ~ 2024.02.18.</title>
      <link>https://jun9985.tistory.com/79</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 19 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 11502 : 세 개의 소수 문제 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Number Theory(Primality Test) + Bruteforcing 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1000 이하의 모든 소수를 찾는 건 그냥 O(N^2)로도 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1000 이하의 소수는 대략 200 개 미만일 것이라 생각해서 세 수를 찾는 건 O(N^3)로 모든 조합을 찾아보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에 소수 찾는 걸 Sieve로 좀 더 빠르게 찾을 수는 있는데... 귀찮아서 구현을 안 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 11332 : 시간 초과 - S3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Case-working 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도를 나타내는 문자열에 따라서 로직을 전부 다르게 구현해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;O(N^2), O(N^3), O(2^N), O(N!)은 오버플로우가 나타날 가능성도 존재하기도 하므로 적절히 커팅해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(나는 N^2은 40000 이상, N^3은 1001 이상, 2^N은 31 이상, N!은&amp;nbsp; 13 이상이면 불가능하다고 커팅해주었다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 12919 : A 와 B 2 - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforcing + Backtracking 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역으로 T에서 S로 바꾸는 게 가능한 지로 판단해보면 T 맨 앞과 맨 뒤의 철자를 가지고 분기점을 나눌 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(앞 뒤가 B면 항상 B를 뒤에 추가 + 뒤집기를 한 것이고, 둘 다 A면 항상 A를 뒤에 추가한 작업을 한 것임. 앞이 B, 뒤가 A면 둘 다 가능성이 있고... 반대로 앞이 A, 뒤가 B면 더 이상 진행할 수 없음.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 근데 시간복잡도 계산이 어떻게 되는지를 잘 모르겠어서 일단 질러본건데... 최악이 O(2^N)일 것 같은데 왜 되는건가 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 12904 : A 와 B - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Greedy + Implementation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역으로 T에서 S로 바꾸는게 가능한 지로 판단하는 문제이긴 한데, 맨 마지막 철자에 따라서 행동이 정해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계속 마지막 철자를 지우되, 마지막이 B였으면 뒤집는 연산도 해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 BOJ 12919랑 같은 난이도로 책정되었는지 잘 모르겠어서 S1로 기여하긴 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 1065 : 한수 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforcing + Math + Implementation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N의 범위가 1000까지 이므로 그냥 1부터 N까지 전부 '한수'인지 아닌지를 확인하면 되는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어차피 '한수' 판별은 세 자리 수일때만 해도 되므로(99까지는 전부 '한수'이고 1000은 '한수'가 아니므로) 100 이상 1000 미만이면 백의 자리 수 - 십의 자리수 = 십의 자리수 - 일의 자리수 를 만족하는지를 확인하면 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S4 치고는 너무 쉬워서 S5로 기여하긴 했는데 B1이라고 해도 납득되었을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. BOJ 19591 : 독특한 계산기 - G3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Deque + Parsing + Implementation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Deque를 활용해서 operator들과 operands를 관리하고, 조건에 따라서 이를 구현하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 깡구현 문제들을 작정하고 푸는게 아니면 싫어하지만, 너무 어려운 구현 문제는 아니어서 괜찮게 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ 27725 : 지수를 더하자 - G4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math + Number Theory 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 ~ K 모든 값에 대해서 각 소수별로 최대 몇 번씩 나눌 수 있는지를 보고 이를 모두 더하면 되는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. BOJ 20930 : 우주 정거장 - P5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sorting + Sweeping + DSU 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 선분을 X축과 Y축으로 투영을 했을 때에 둘 중 한 축에서 서로 겹친다면 두 선분끼리는 서로 갈 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 모든 선분들을 X축 및 Y축으로 투영을 하고, X나 Y 좌표가 낮은 순서대로 정렬해서 Sweeping을 하면 O(NlogN)만에 어느 선분끼리 겹치는지를 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;겹치는 선분끼리는 DSU를 활용하여 같은 그룹으로 묶어둘 수 있고, 각 쿼리별로 같은 그룹에 있는지 확인해서 응답해줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 시간복잡도는 O(NlogN + Q*t(N)) // t(N)은 DSU cost 값, 매우매우 작은 값이라고 알고있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9 ~ 13. 제 3회 보라매컵 본선 Open Contest (Arena #20) - Solved : 5 / 8&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 후기로 올리긴 할텐데...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반성을 매우 많이 해야겠다는 생각이 들었던 대회였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 5 문제중에 첫트로 AC받은 문제가 없지;;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;14 ~ 16. SUAPC 2024 Winter Open Contest - Solved : 3 / 13&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 15분 정도 남았을 때부터 참가해서 그냥 스코어보드에서 제일 많이 풀린 세 문제만 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 따로 후기 올릴 생각없으니 여기에 쓰겠음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;14. BOJ 31428 : 엘리스 트랙 매칭 - B4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 'A', 'C', 'S', 'I' 개수 다 세고, 마지막 줄에 주어진 철자의 개수를 출력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 브론즈는 리뷰 안 하지만 대회 문제니깐...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15. BOJ 31416 : 가상 검증 기술 - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Simulation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단, 도훈이만 B 작업을 할 수 있으므로 도훈이에게 전부 B 작업을 맡기고, 그 동안에 상혁이에게 A를 맡긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 둘 중에 먼저 빨리 끝난 사람에게 A 작업을 맡기면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 구현은 B 작업이 남았으면 도훈이에게 할당, 작업이 없으면 일이 더 빨리 끝난 사람에게 A 할당 이런식으로 하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15. BOJ 31423 : 신촌 통폐합 계획 - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 DSU로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 다음 어느 문자열이 오는지를 저장하는 배열 next와 해당 문자열 뒤에 붙인다면 어느 문자열 뒤에 붙이는 지를 판단하는 배열 p를 선언하자. 초기화는 전부 next[i] = i, p[i] = i로 해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면, 문자열 a 뒤에 b를 붙이는 걸 DSU merge 함수를 활용해서 구현이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에, next에 없는 문자열이 제일 먼저 나오는 문자열이므로 해당 문자열부터 next 배열을 타면서 순서대로 출력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 정해는 DFS 풀이나 연결 리스트로 구현하는 거라고 한다. (나도 연결 리스트까지 생각은 해보긴 했는데 시간이 부족했어서 구현까지 할 엄두가 안 났었다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에도 브론즈 4 문제를 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/79</guid>
      <comments>https://jun9985.tistory.com/79#entry79comment</comments>
      <pubDate>Mon, 19 Feb 2024 08:49:48 +0900</pubDate>
    </item>
    <item>
      <title>2024.02.05. ~ 2024.02.11.</title>
      <link>https://jun9985.tistory.com/78</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 16~17문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 23760 : 까다로운 아이들과 선물 상자 - P5 (업다운 랜덤디펜스 성공! Solved - 18:01)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Segment Tree + Binary Search 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리 순서대로 K 번째로 큰 수를 Segment Tree에 쿼리를 날려서 찾고 이를 업데이트 해주는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리는 Binary Search를 응용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 쿼리 순서를 마음대로 바꿔도 되는가 싶어서 예제가 이해 안 되었는데, 나중에보니 순서가 고정이라서 쉽게 풀었던 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 23757 : 아이들과 선물 상자 - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Priority Queue 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 BOJ 23760을 푼 김에 같이 풀어본 문제였는데, K=1이 고정인 문제여서 PQ로 풀 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PQ 공부하기 좋은 문제라 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 31404 : 아리스, 청소합니다! - G3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Simulation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맵의 범위가 작아서 시뮬레이션을 최대 4천만번만 돌리도록 구현해서 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드록 범위를 정하느라 계속 틀렸다가 맞은 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 18265 : MooBuzz - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Binary Search + Math 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mid 값에 대해서 mid - mid/3 - mid/5 + mid/15의 값이 N 이상인지 아닌지를 판단하여 l,r을 업데이트 해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 Binary Search 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 26156 : 나락도 락이다 - G4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP + Combinatorics 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i번째 index의 R이 마지막 R인 문자열 개수는 2^i 개가 가능하며, j 번째 index의 O,C,K는 각각 j 번째 전에 나온 R, O, C가 마지막 R, O, C인 경우의 수들의 합과 동일하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이걸 BOJ 30880 풀기 전에 풀어보았는데... 그래도 BOJ 30880은 감이 안 온다;;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. BOJ 2104 : 부분배열 고르기 - P5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Prefix Sum + Monotone Stack 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음수가 존재하지 않으므로, v[i]가 최솟값인 구간 중에서 제일 값이 큰 구간은 v[i] 기준으로 연속되게 양 옆으로 최대한 뻗으면서 v[i]가 최솟값인 구간이 답이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이는 히스토그램 문제처럼 풀 수 있는데, 일반적인 히스토그램은 양 옆으로 최대한 뻗은 길이 * 값을 구한다면, 여기서는 최대한 뻗은 구간 합 * 값으로 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 시간복잡도는 O(N). 오랜만에 보는 Monotone Stack 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[모두의 랜덤 디펜스] - 중급 코딩테스트 (B2 ~ G4)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험 시간 : 60 분, 실제 : 23 분만에 올솔.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Solved : 3 / 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7.&amp;nbsp; BOJ 25966 : 배찬우는 배열을 좋아해 - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Implementation + Tree set으로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히는 Tree map으로 쿼리에서 인덱스를 주면 실제 배열에서의 인덱스를 반환해주는 테이블을 구현했고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에는 쿼리 처리하는 것을 구현했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 사실 굳이 Tree map이 아니라 배열 하나 더 선언해서 테이블을 구상했으면 실행속도가 더 빨랐을 듯?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 시간복잡도는 O(QlogN)이긴 한데, 배열이면 O(Q)도 가능했을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. BOJ 19941 : 햄버거 분배 - S3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Greedy 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에 있는 사람이 못 먹는 햄버거는 뒤에 있는 사람도 못 먹는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 아이디어로 앞의 사람부터 하나하나씩 매핑을 해준다. 그러다가 햄버거가 사람 위치 + K 넘으면 다음 사람에게 매핑을 해줘본다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Queue 두 개를 선언해서 풀어주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. BOJ 22342 : 계산 로봇 - S1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[i][j] = max(dp[i-1][j-1] + d[i-1][j-1], dp[i][j-1] + d[i][j-1], dp[i+1][j-1] + d[i+1][j-1]) 로 풀면 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 세 칸만 보면 되냐면, 저 세 dp 칸들은 결국 뒤에 있는 삼각형들로 나올 수 있는 최댓값이 저장되어 있을 것이고, d값이 항상 양수이므로 뒤의 세 칸만 보는게 제일 이득이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10. BOJ 2303 : 숫자 게임 - S5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforcing + Implementation 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5C3은 10밖에 안 되므로 사람별로 모든 조합에 따라서 일의 자리가 최대인 수를 찾아보고, 그 중에서 이제 비교해보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11. BOJ 1548 : 부분 삼각 수열 - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforcing + Greedy + Sorting 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 여기에다가 Binary Search를 더 박아서 풀긴 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수열 내에 제일 작은 두 값을 더한 게 제일 큰 값보다 커야 하므로, 제일 작은 두 값을 설정했을 때에 어디까지 뻗을 수 있는지를 확인해보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5~6 문제 Bronze.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/78</guid>
      <comments>https://jun9985.tistory.com/78#entry78comment</comments>
      <pubDate>Sun, 11 Feb 2024 22:52:02 +0900</pubDate>
    </item>
    <item>
      <title>PS 문제를 풀 때 유용한 팁들</title>
      <link>https://jun9985.tistory.com/77</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;제가 지금까지 PS 문제를 풀 때 깨달은 유용한 팁들을 한 번 공유해보고자 합니다. 들어가기 앞서서, 여기에 적은 내용들은 전부 지극히 저의 주관적인 생각들입니다. 따라서 제 생각이 틀렸을 수 있으니 참고만 하시면 좋습니다. 그리고 피드백은 언제나 환영이니 댓글로 마음껏 해주시면 감사하겠습니다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 시간 제한은 1초에 1억(10^8)번 연산이 가능하다고 생각하는게 편합니다. &lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 '1초 = 1억번의 연산'이라는 가정을 세우고 가능한 시간복잡도를 계산해봅니다. 주로 정해의 시간복잡도에 따른 연산 횟수를 계산해보면 이 공식이 맞는 것 같습니다. 물론 연산이 간단한가 어려운가에 따라서나 붙는 상수에 따라서 1초에 가능한 연산의 횟수가 커질 수 있긴 합니다. (그래서 저도 계산을 해보았을 때, 1억번을 '약간' 넘는 경우라면 그냥 한 번 시도를 해봅니다.) 그래도 '1초 = 1억번' 이 공식으로 문제를 풀었을 때는 TLE 난 경험은 거의 없었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 알고리즘이 시간내에 돌아갈 수 있음을 시간복잡도로 증명을 할 수 있지만, 역으로 가능한 시간복잡도로 어느 알고리즘이 정해일 지 유츄가 가능합니다. &lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 제한에 알맞는 시간복잡도를 먼저 계산하면 이와 같거나 더 빠른 알고리즘들만 고려하는 것으로 선택의 폭도 줄일 수 있습니다. 예를 들어서, 최단거리 문제인데 정점의 개수 V 및 간선의 개수 E에 따라서 가능한 시간복잡도가 O((V+E)logV)까지만 가능하다면 이보다 더 느린 시간복잡도를 가진 O(VE)나 O(V^3)인 Bellman-Ford나 Floyd-Warshall은 고려대상에서 없앨수가 있죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 예외는 있을 수가 있습니다. 사이트나 채점 시스템 특성상 시간복잡도 상으로는 더 느려도 코드가 더 빠르게 돌아가는 경우도 존재합니다. 이러한 경우에는 시간복잡도에는 붙지 않은 상수가 매우 커서 그럴수도 있습니다. (예전에 SW Expert Academy에서 이런 증상을 가끔씩 겪어봤던 것 같습니다. SW Expert Academy 서버가 좀 상수 영향을 매우 받아서 그런지 상수 커팅이 중요했던것 같습니다.)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. PS를 할 때는 본인이 제일 자신있는 언어로 시작하는게 제일 좋습니다. &lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언어들마다 항상 장단점은 존재합니다. 예를 들어서 제가 사용하는 언어 중 제일 빠른 C++과 제일 느린 Python을 비교해서 설명해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C++&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엄청 빠릅니다. 어지간한 문제들은 C++로는 항상 풀립니다. Competitive Programming에서는 특정 언어에서는 못 풀 수 있는&amp;nbsp;&lt;/li&gt;
&lt;li&gt;재귀 깊이도 파이썬에 비해서 훨씬 문제가 없습니다. 그리고 무려 PBDS나 Rope같은 자료구조들도 지원합니다.&lt;/li&gt;
&lt;li&gt;C를 해보았다면 STL이랑 C++ 문법 몇 개만 추가적으로 공부하면 됩니다.&lt;/li&gt;
&lt;li&gt;#include &amp;lt;bits/stdc++.h&amp;gt; 이렇게 어지간한 라이브러리들을 묶어놓은게 있어서 어느 라이브러리에 뭐가 있는지를 굳이 안 외우고도 풀 수 있다는 소소한 장점이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;큰 수 연산이나 모듈로 역원 등. 수학 관련하여 직접 구현하는 방법 및 사전 지식을 알고 있어야 구할 수 있습니다. (저만 해도 FLT로만 구현할 줄 알다보니 모듈로를 해주는 값이 소수가 아니면 확장 유클리드 호제법을 몰라서 못 구해요...)&lt;/li&gt;
&lt;li&gt;문자열을 조작하는 문제등이 나오면 불편하기도 합니다. 특히나 저 같은 경우에는 한 번에 받아야 할 문자열이 공백으로 구분이 되는게 아니라면 그냥 Python을 사용합니다.&lt;/li&gt;
&lt;li&gt;같은 걸 구현하더라도 C++은 Python에 비해서 비교적 더 길게 적어야 합니다. 그래서 실제로 쉬운 문제라면 저도 그냥 Python을 씁니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Python&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;큰 수 연산이 가능합니다. (큰 수 연산이 지원이 안 되는 C나 C++에서는 곱셈을 해야하면 고급 알고리즘인 FFT를 사용해야합니다. BOJ 13277과 BOJ 15576의 난이도를 비교해보시면 체감이 될 겁니다.)&lt;/li&gt;
&lt;li&gt;그리고 모듈로 역원을 찾는 함수 등 든든한 built-in 함수들이 많습니다.&lt;/li&gt;
&lt;li&gt;문자열 조작도 쉬운 편입니다. 그래서 실제로 문자열 문제라면 저도 Python을 씁니다.&lt;/li&gt;
&lt;li&gt;코드 길이가 비교적 짧아서 읽기도 편합니다. 또한, 배우기도 엄청 쉬운 언어기도 하구요.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;너무 느려서 시간복잡도 상으로는 괜찮아도 억까를 당하는 경우도 존재합니다. 시간 제한을 더 줘도 못 푸는 경우도 있더라구요.&lt;/li&gt;
&lt;li&gt;또한, 재귀 깊이에 상한선이 존재해서 필요시에는 비재귀로 구현하는 테크닉을 활용해야하는 경우도 있다고 합니다. (물론 재귀 깊이를 새로 설정해줄 수 있지만, 메모리가 터지는 경우도 있습니다.)&lt;/li&gt;
&lt;li&gt;Multiset을 지원해주지 않는 걸로 알고 있습니다. 또한, PBDS나 Rope를 지원해주지 않는 점도 있습니다. (PBDS는 Segment Tree + Binary Search + Value Compression을 다 구현해주면 되긴 합니다. Rope는 저도 트리 자료구조인 점 빼고는 잘 모르긴 해요.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇듯 언어별로 장단점이 존재합니다. 그리고 느린 언어라고 해서 Competitive Programming 등이 아에 불가능하지는 않습니다. 제 주변에 지인만 봐도 Python 유저인데 코드포스 오렌지까지 달았던 사람도 보기도 했습니다. 그리고 코딩테스트 같은 환경은 아에 Python으로도 풀리도록 문제가 갖춰져 있을테니 PS 목적이 코딩테스트 공부라면 더욱이나 상관 없습니다. 본인이 많이 사용해본 걸로 시작하세요!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3-1. 다만 본인이 PS는 처음이고 어느 언어로 시작할지 모른다면 조심스럽게 한 번 C++로 시작 해보시는 걸 추천드립니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++를 한 번도 안 배워봤다고 해도 C는 전공 수업 등으로 한 번쯤 공부해보셨을 것이라 생각합니다. C를 해봤다면 C++도 그리 어렵지 않는게 PS를 하면서 쓰는 기술은 사실상 C와 STL밖에 없기 때문입니다. 애초에 C++를 사용하는 이유도 C의 빠른 속도와 우수한 STL을 활용하기 위해서 그렇다고 생각합니다. 그래서 추가적으로 STL이랑 Fast I/O 및 C++ 문법을 몇개 정도 익혀두면 C++로도 쉽게 문제를 풀 수가 있습니다. 이렇게 C를 해본 입장에서는 배우기도 쉬우면서도 속도도 빨라서 상수 커팅 등등을 어느정도 덜 신경써도 되기도 해서 저는 C++를 추천드립니다. 실제로 최상위 잘 하는 사람들은 주로 C++로 문제를 풉니다. (Rust도 쓰는 것 같긴 한데, 일단 제가 저 언어를 몰라서 패스하겠습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;다만 C도 안 했거나 자신이 없는데 시간도 없다면 배우기 쉬운 Python을 쓰는 것을 추천드립니다. Python이 그리 어려운 언어도 아니기도 하고, 문제가 생겼을 때 C++의 Segmentation Fault 같이 직접 디버깅을 해서 원인을 알아내야 하는 경우도 거의 없고 어디서 문제가 생겼는지를 인터프리터가 직접 짚어주기도 때문에 디버깅도 쉽습니다. 다만 대회까지 생각이 있으면 시간을 내서 C++도 익히는 걸 추천드립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 문제를 풀 때 가능하다면 랜덤디펜스를 하는 게 실력 향상에 제일 도움이 되는 것 같습니다.&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 설명하기 앞서서 저는 랜덤디펜스를 백준에서만 했기 때문에 백준 위주로만 설명하겠습니다. Programmers이나 SWExpertAcademy, Softeer 같은 경우에는 난이도가 어차피 백준에 비해 세부적으로 나누어져 있지 않아서 밑에서 제가 설명할 방법처럼 할 필요는 없고 그냥 어느 알고리즘을 사용하는지 가리고 풀면 될 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Competitive Programming이나 코딩테스트에는 어느 알고리즘의 문제가 나올지는 아무도 모릅니다. 본인이 아무리 그래프 문제를 잘 푼다고 하더라도 문제가 전부 DP, 수학, 애드 혹으로만 나올 수도 있습니다. 물론 대회 특성상 선호되어 자주 출제되는 알고리즘도 존재하기도 하고, 난이도가 너무 높은 경우에는 안 나오는 경우도 있습니다. 그래도 의도치 않게 해당 문제들이 나와도 풀 수가 있어야 하며 이러한 능력을 향상 시키는 데는 랜덤디펜스가 제일 좋은 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;랜덤디펜스는 문제의 난이도 및 알고리즘 태그를 가리고 랜덤하게 문제를 선정해서 시간제한 내에 푸는 겁니다. 세부적인 방법은 각각 사람마다 다를 수 있는데 크게 두 가지가 있는 것 같습니다. 첫 번째로는 난이도 범위를 정하고 랜덤하게 문제들을 받아서 푸는 방법이 있고, 두 번째로는 첫 시작을 어느 난이도로 찝어서 시간 내에 풀면 다음에는 더 높은 난이도를, 풀지 못하면 더 낮은 난이도 문제를 도전하는 방법이 있습니다. (두 번째 방법은 업다운 랜덤디펜스라고도 합니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 랜덤디펜스라고 해서 모든 태그를 꼭 풀거나 그럴 필요가 없습니다. 본인이 너무 자신이 없거나, 몰라서 공부한 후에 보고싶은 태그들은 제외해서 랜덤디펜스를 돌리기도 합니다. 또한, 푼 사람 수가 너무 적으면 틀렸을 때 답을 복기할 수 없는 경우가 생길 수도 있어서 푼 사람수가 몇 명 이상인 문제들만 랜덤하게 받기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 랜덤디펜스 돌리는 것을 예시로 삼아서 설명해보겠습니다. 저는 두 가지 방법을 모두 병행합니다. 공통적으로 저는 아래와 같이 제한을 둡니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;푼 사람수 100 명 이상&lt;/li&gt;
&lt;li&gt;기하 및 내가 아에 모르는 태그는 제외&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 조건속에서 저는 여유가 있으면 G3 ~ P5 문제를 아니면 G5 ~ G3 사이의 문제들 중에서 랜덤하게 풉니다. 업다운 랜덤디펜스는 G5부터 시작해서 현재 G3에 머물러 있구요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 제가 어쩌다가 알게된&amp;nbsp;&lt;a href=&quot;https://morandi.co.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;모두의 랜덤디펜스&lt;/a&gt; 사이트를 활용해서도 가끔씩 랜덤디펜스를 돌리는데, 여기서는 제가 잘 모르는 태그도 없기도 하고 난이도 폭도 적당해서 이 사이트를 활용하는 것도 좋아보입니다. 코딩테스트 준비하기도 괜찮을 것 같구요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에는 (물론 위의 글들도 모두 제 주관이 들어갔지만)아주 개인적인 저의 생각들입니다. 이 부분에 대해서는 의견이 좀 갈릴 수는 있어는 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저는 새로운 태그를 공부한다면 이에 대한 예제나 기본 문제 몇 개 정도는 인터넷에 있는 답을 참고해서 푸는 것도 좋은 방법이라 생각합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이를 통해서 해당 태그가 어떤 식으로 응용되는지 및 어떤 유형의 문제의 꼴을 가지고 있는지 등을 파악할 수도 있고, 구현도 반복하게되어 로직도 익히면서 손에도 해당 알고리즘이 익히겠죠.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Greedy 문제들은 평소에 문제를 풀 때, 증명하는 과정도 꼭 해보는게 필요하다고 생각합니다. 아에 수식적으로 증명하면 베스트이긴 하지만, 그게 안 되더라도 '~를 하니 이렇게 greedy하게 풀린다~' 이런 생각하는 연습은 필요한 것 같습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저도 어지간하면 이렇게 증명을 최대한 해서 푸는 연습을 합니다. 물론 저도 시간제한이 있는 등의 이유로 대충 짐작해서 greedy하게 푸는 경우도 있지만, 이렇게 푼 문제들은 나중에 왜 이게 greedy하게 풀 수 있었는지 고민을 해봅니다. 이러한 연습들이 있어야 실제 대회나 코딩테스트에서도 greedy 문제가 나오면 greedy일 것이라는 감도 잘 오고 본인의 풀이에 더욱 확신을 갖게 되는 것 같습니다. 그리고 이런 연습을 해야 AC를 대회나 시험 끝나고 알 수 있는 환경에서는 본인의 풀이를 검토할 수가 있겠죠? (예 : HSAT, 삼성전자 B형 Pro 검증, HackerCup)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DP 문제들은 greedy 보다도 수식으로 꼭 증명해보는 연습이 필요하다고 생각합니다. 결국 DP 문제의 제일 큰 난관은 'DP 테이블을 어떻게 짤 것인가?'인데, 이는 평소에 수식으로 증명하는 연습을 해야 수월하게 계산이 되는 것 같습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;또한, 너무 웰노운 DP(예: Knapsack DP, MCM DP 등등.)더라도 그냥 수식을 외우는게 아니라 수식을 이해를 해야 이걸 한 번 꼬아서 DP 테이블에 약간의 variation이 들어간 문제도 쉽게 풀 수 있다고 생각합니다.&lt;/li&gt;
&lt;li&gt;이것외에도 DP는 크게 보았을 때의 Knapsack DP, LIS, MCM DP 등등. 특정 유형으로 귀결되는 경우들이 종종 있어서 여러 유형의 DP들을 꼭 풀어보는 것도 중요한 것 같습니다. 저는 만약에 현재 풀고 있는 DP문제가 어떤 유형인지 파악했으면은 해당 DP에서의 유명한 점화식을 조금만 더 비틀면 어지간하면 다 풀렸었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;처음으로 PS를 한다면 기본적인 알고리즘들을 먼저 BFS식으로 하나하나 훑어보는게 더 나은 것 같습니다. 특정 알고리즘을 깊게 파는 것은 좀 비추천드립니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 깊게 파는 것에 대한 기준은 다음과 같습니다. 실제 제가 했던 예시를 들자면, 저는 Sudoku 문제에서 Backtracking 문제가 재밌어서 DP / Greedy 등의 문제들도 제대로 모르는 상태에서 Dancing Link + Knuth X 알고리즘을 공부했었습니다. 또한, 기하학도 궁금해서 DP / Greedy 보다 Graham Scan을 먼저 공부했었고요...(각각 Solved.ac 기준으로는 D2, P5에 해당되는 알고리즘들 입니다.) 또한 Segment Tree가 그렇게 사기라길래 실랜디도 안 되는 상황에서 공부했었습니다.&lt;/li&gt;
&lt;li&gt;이렇게 깊게 파는 것을 추천드리지 않는 이유는 간단합니다. 어차피 본인이 기본 실력이 없는데 이런 어려운 알고리즘들을 배워도 응용 문제들은 못 풉니다. 그리고 사실 어려운 알고리즘들이면 기본 실력도 없으면 이해하기도 어려워요.&lt;/li&gt;
&lt;li&gt;그래서 저는 전체적으로 기본적인 Bruteforcing / DP / Greedy / Graph(탐색, 최단거리 등등.)등을 먼저 공부하는게 좋다고 생각합니다. 적어도 최소 골드 하위권(G5 ~ G4)까지의 문제 유형들을 아직 공부해보지 못했다면 이렇게라도 먼저 공부를 하는게 좋다고 생각해요.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지가 제가 생각나는대로 적은 팁들입니다. 추가적으로 생각나는게 있다면 다시 업데이트를 해보도록 하겠습니다.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/기타</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/77</guid>
      <comments>https://jun9985.tistory.com/77#entry77comment</comments>
      <pubDate>Wed, 7 Feb 2024 22:26:45 +0900</pubDate>
    </item>
    <item>
      <title>[C++] Dijkstra 역추적하는 방법</title>
      <link>https://jun9985.tistory.com/76</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이번 글에서는&lt;b&gt; Dijkstra 알고리즘을 역추적&lt;/b&gt;하는 방법에 대해서 설명해보고자 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Dijkstra 관련 문제들을 풀다보면 가끔씩 최단 경로를 출력하라는 문제들을 볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이럴 때에는 도착 노드부터 시작 노드까지 역으로 추적하는 방법으로도 최단 경로를 찾을 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그러면 어떻게 역추적을 하면 될까요? 일단 최단 경로의 특성에 대해서 알아보도록 합시다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;노드 A, B가 각각 시작 노드와 도착 노드&lt;/b&gt;라 합시다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그리고 &lt;b&gt;A와 B간의 최단 경로에 K라는 노드가 속할 수 있다&lt;/b&gt;고 합시다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그렇다면 다음과 같은 식이 성립합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;A -&amp;gt; B의 최단 거리 = (A -&amp;gt; K의 최단 거리) + (K -&amp;gt; B의 최단 거리)&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이러한 식은 A -&amp;gt; B의 최단 경로에 속하는 모든 노드들에 대해서 적용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그렇다면&lt;u&gt; &lt;b&gt;A -&amp;gt; K의 최단 거리 = (A -&amp;gt; B의 최단거리) - (K -&amp;gt; B의 최단거리)&amp;nbsp;&lt;/b&gt;&lt;/u&gt; 이러한 식도 말이 되겠지요?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이러한 특징으로 역추적이 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;최단 경로 중에서 B 노드 바로 전에 들리는 노드를 B'라고 합시다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그렇다면 &lt;b&gt;B' -&amp;gt; B의 최단거리 = B' -&amp;gt; B로 가는 간선의 거리&lt;/b&gt;가 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그렇다면 &lt;b&gt;A -&amp;gt; B'의 최단거리 = (A -&amp;gt; B의 최단거리) - (B' -&amp;gt; B 간선의 거리)&lt;/b&gt; 이게 만족하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그러면 이제&lt;b&gt; B' 노드를 들리기 직전에 들리는 B''라는 노드&lt;/b&gt;는&lt;b&gt; A -&amp;gt; B'' 의 최단거리 = (A -&amp;gt; B'의 최단거리) - (B'' -&amp;gt; B' 간선의 거리)&lt;/b&gt;를 만족합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 역추적을 하는 방법은 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. 도착 노드 &lt;u&gt;B부터 보기 시작&lt;/u&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2.&amp;nbsp;현재 보고 있는 노드를 curr이라고 하자, 그리고 curr를 도착점으로 하는 간선들의 시작점을 bef라고 하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그렇다면 &lt;u&gt;A -&amp;gt; bef의 최단거리 = (A -&amp;gt; curr의 최단거리) - (bef -&amp;gt; curr의 간선의 거리)를 만족하는 아무 노드 bef를 찾는다.&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;3. 그렇다면 &lt;b&gt;&lt;u&gt;최단경로 상에서 bef가 curr 전에 들리는 노드&lt;/u&gt;&lt;/b&gt;이므로 &lt;u&gt;curr를 bef로 업데이트&lt;/u&gt; 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;4. curr가 시작 노드인 A가 되면 그만둔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이러면서 curr를 계속 기록을 해두면 됩니다. curr == A 가 되는 순간에는 이제 기록해둔 것을 거꾸로 뒤집으면 최단경로가 나옵니다. C++ 코드로는 아래와 같이 구현하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1707302820185&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 전에 이미 선언되어 있는 것들
// #define ll long long
// vector&amp;lt;ll&amp;gt; dist(N+1) : 시작점으로 각 노드까지의 최단거리를 담은 array. Dijkstra를 돌린 결과.
// vector&amp;lt;vector&amp;lt;pair&amp;lt;ll,ll&amp;gt;&amp;gt;&amp;gt; E2(N+1) : E2[n] = n이 도착점인 간선들의 정보, 각 간선들은 {간선의 시작점, 간선의 거리}로 표현됨 

vector&amp;lt;ll&amp;gt; path; // 최단경로
ll curr = B;
while(curr != A){
	path.push_back(curr);
    for(auto itr : E2[curr]){ // 역간선들을 보았을 때에
    	ll bef, cost;
        tie(bef, cost) = itr;
        if(dist[bef] = dist[curr] - cost){ // A -&amp;gt; bef 최단거리 = A -&amp;gt; curr 최단거리 - bef -&amp;gt; cost 간선의 거리를 만족하면
        	curr = bef; // curr 업데이트
            break;
        }
    }
}
path.push_back(A); // 시작점도 넣어줌
reverse(path.begin(), path.end()); // 뒤집으면 최단 경로를 담은 array가 됨&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이번 글에서는 Dijkstra 알고리즘을 역추적하여 어떻게 최단 경로를 찾는지에 대해서 알아보았습니다. 다만, 이렇게 구한 최단 경로는 가능한 최단 경로들 중 하나만 찾습니다. (최단 경로는 여러 가지가 존재할 수 있습니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;다음에 다룰 알고리즘은 어떤 알고리즘일지 모르겠습니다. 또 생각나는게 있으면 다뤄보도록 할게요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;추천 문제&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;BOJ 11779 : &lt;a href=&quot;https://www.acmicpc.net/problem/11779&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;최소비용 구하기 2&lt;/a&gt;&lt;/b&gt; - Dijkstra 역추적 기본 문제입니다. 위의 알고리즘을 그대로 적용하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;BOJ 31230 : &lt;a href=&quot;https://www.acmicpc.net/problem/31230&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;모비스터디&lt;/a&gt;&lt;/b&gt; - 또 다른 Dijkstra 역추적 문제입니다만, 여기서는 최단 경로에 들어갈 수 있는 모든 정점들에 대해서 찾아보아야 합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;BOJ 5719 : &lt;a href=&quot;https://www.acmicpc.net/problem/5719&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;거의 최단 경로&lt;/a&gt;&lt;/b&gt; - 매우 유명한 Dijkstra 역추적 문제입니다. 최단 경로에 들어갈 수 있는 모든 간선들을 확인해봅시다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/Algorithm</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/76</guid>
      <comments>https://jun9985.tistory.com/76#entry76comment</comments>
      <pubDate>Wed, 7 Feb 2024 21:53:31 +0900</pubDate>
    </item>
    <item>
      <title>Dijkstra(다익스트라)를 내가 이해한 방식대로 설명해보기 (feat. BFS)</title>
      <link>https://jun9985.tistory.com/75</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이번에는 Dijkstra 알고리즘에 대해서 설명을 해볼건데, 제가 이해한 방식으로 한 번 설명을 해보려고 합니다. 따라서 이게 옳은 설명인지에 대해서는 엄청 확신이 들지는 않지만 그래도 알고리즘 기본적인 작동방식을 이해하기는 쉽지 않을까 생각해봅니다. (그래서 정확한 증명보다는 이해하는데에 좀 더 집중을 하면 좋을 것 같습니다!) 그 전에 앞서서 일단 BFS 알고리즘의 특성에 대해서 설명해보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;BFS&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;BFS(Breadth First Search)&lt;/b&gt;는 그래프 탐색 방법 중 하나인데, 특정 노드부터 시작해서 근처에 있는 순서대로 탐색을 하는 방법입니다. 구현을 할 때에는 주로 &lt;b&gt;Queue로 구현&lt;/b&gt;을 하는데, &lt;u&gt;Queue에 나오는 순서는 시작한 노드에 근처에 있을 수록 더 빨리 나옵니다.&lt;/u&gt; 이러한 특징 때문에 &lt;u&gt;간선들의 비용이 모두 동일한 상황에서의 최단거리 문제에서는 BFS를 사용&lt;/u&gt;합니다. (예 : 미로 찾기 등의 문제에서 '출구까지의 최단거리' 등을 찾는 문제) 후술할 다익스트라 알고리즘의 시간복잡도보다 더 빠른 &lt;b&gt;O(V+E)&lt;/b&gt;만에 풀 수 있기 때문이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;다만, &lt;u&gt;BFS를 통해서 푸는 최단거리 문제는 간선들의 비용이 모두 동일한 경우&lt;/u&gt;에만 재미를 볼 수 있습니다. BFS를 사용해서 최단거리를 찾을 수 있는 이유는 항상 Queue에서 지금 나온 노드가 다음에 나올 노드들보다 항상 거리적으로 더 가깝거나 같기 때문인데, 만약에 간선들의 비용이 다르다면 이러한 가정이 더 이상 성립하지 않기 때문입니다. 따라서 간선들의 비용이 다르다면 그냥 BFS를 하면 안 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Dijkstra&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그런데 만약 가중치가 음인 간선이 없다면, 현재 찾은 노드들 및 해당 노드까지 도달한 거리에 대해서 아래와 같은 가정은 성립합니다. Queue에 {노드, 해당 노드까지 계산된 거리} 이렇게 두 가지의 정보를 넣는다면...&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;현재 Queue에 들어간 {노드, 해당 노드까지 계산된 거리}들 중 '해당 노드까지 계산된 거리'가 제일 짧은 거리의 노드를 우선적으로 BFS를 돌린다면, 해당 노드가 Queue에서 나온 적이 없는 경우에는 '해당 노드까지 계산된 거리' = 해당 노드까지의 최단거리가 된다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt; &lt;span style=&quot;font-family: 'Nanum Gothic'; color: #666666; text-align: left;&quot;&gt;만약 업데이트가 되어있다면 이미 최단 거리는 찾은 상태이니 넘어가면 됩니다. 그러면 &lt;/span&gt;이게 왜 성립을 하는지 설명을 해보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. 현재 Queue에서 제일 짧은 '해당 노드까지 계산된 거리'가 k라고 합시다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. 그러면 &lt;u&gt;k까지 계산된 거리를 포함해서 최단거리를 갱신하는 거리는 k 이상의 값&lt;/u&gt;이 될 겁니다. (음의 간선이 없기 때문이죠.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;3. 따라서 &lt;u&gt;Queue에 이후에 들어올 '해당 노드까지 계산된 거리'는 k 이상의 값&lt;/u&gt;이 들어옵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;4. 이를 통해서 &lt;u&gt;Queue에서 '해당 노드까지 계산된 거리'가 짧은 순서대로 BFS를 돌린다면, '해당 노드까지 계산된 거리'는 항상 단조 증가함을 보이는 걸 확인&lt;/u&gt;할 수 있습니다. (증가하거나, 아니면 값이 그대로거나)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;5. 그렇다면&lt;u&gt; Queue에서 특정 노드가 아직 한 번도 Queue에서 나온적이 없으며 이번에 처음으로 나왔다면 그때 같이 '해당 노드까지의 계산된 거리'가 실제 해당 노드까지의 최단거리&lt;/u&gt;가 됩니다. 이후에 나오는 값들은 해당 값보다 더 크게 나오기 때문이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Queue가 들어온 정보들 중에서 &lt;u&gt;'해당 노드까지 계산된 거리'가 제일 짧은 것을 먼저 계산할 수 있도록 설계가 되어있으면 BFS를 하는 것만으로도 최단거리를 찾을 수 있습니다.&lt;/u&gt; 그렇다면 '해당 노드까지 계산된 거리'가 제일 짧은 것을 우선적으로 처리해줄 수 있는 자료구조가 무엇이 있을까요? 맞습니다. &lt;b&gt;Priority Queue&lt;/b&gt;를 사용하면 됩니다. 따라서 &lt;b&gt;총 시간복잡도는 Priority Queue의 시간복잡도가 O(log V)가 되므로 O((V+E) log V)&lt;/b&gt;가 됩니다. 이러한 알고리즘이 바로 &lt;b&gt;Dijkstra&lt;/b&gt;입니다. (저는 이렇게 이해했습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Dijkstra 구현도 간단합니다. 사실상 &lt;b&gt;BFS에서 Queue 대신에 Priority Queue로 바꿔주면 Dijkstra 알고리즘&lt;/b&gt;이 됩니다. 다만 그냥 BFS 코드에서 Priority Queue로 구현하면 실제 계산량은 제대로 구현한 것과의 차이가 엄청나기 때문에 좀 수정이 필요합니다. 잘못 구현한 Dijkstra는 저격이 가능합니다. 그래서 제대로 구현하는 방법을 꼭 알고 있어야 합니다. (그래도 BFS를 좀만 수정하기 때문에 제대로 구현하는 것도 쉬워요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Python 비스무리한 Psuedo code로 Dijkstra 구현 코드를 적으면 아래와 같습니다. PQ &amp;lt;- 는 Priority Queue로 push, &amp;lt;- PQ는 pop을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1707300224484&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dist[src] = 0 		# 시작점은 거리가 0으로 초기화
PQ &amp;lt;- {0, src} 		# PQ에 {시작점까지의 거리, 시작점}을 넣고 초기화

while PQ is not empty:
	{distance, node} &amp;lt;- PQ 	# distance가 제일 짧은 값과 해당되는 node를 pop
	if dist[node] &amp;lt; distance : continue	# node가 이미 PQ에서 나온적이 있으면 skip
	for {cost, next_node} in E[node]:
		if dist[next_node] &amp;gt; cost + distance:	# node를 거쳐서 가는게 더 짧다면
			dist[next_node] = cost + distance
			PQ &amp;lt;- {distance + cost, next_node}	
			# next_node의 최단거리를 미리 업데이트 및 PQ에 {node를 거친 next_node까지의 최단거리, next_node}를 push&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대강 이렇게 짭니다. 중요한 점은 한 번 방문한 노드를 다시 업데이트 하지 않고, 최단거리 계산을 미리 해두어 PQ에 들어오는 정보들을 줄이도록 구현을 해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 Dijkstra에 대한 설명이었습니다. 제가 증명보다는 직관적으로 이해할 수 있게 Dijkstra = BFS + Priority Queue 이렇게 야매로 설명을 한지라 제가 설명한 게 정확히 맞는 말은 아닐수도 있습니다. 그래도 작동원리에 대해서 이해하기에는 무리가 없을 것이라 생각합니다. 적어도 Dijkstra 알고리즘을 좀 더 쉽게 이해하는데에 도움이 되셨으면 좋겠습니다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Priority Queue의 시간복잡도에 대한 추가적인 설명&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 왜 Priority Queue의 시간복잡도가 O(log V)가 될까요? Priority Queue에는 V개의 정보 이상이 들어올 수 있을텐데 말이죠. 맞습니다. Priority Queue에는 최대 E개의 정보들이 들어올 수 있습니다. 그런데 E는 V^2를 넘을 수가 없습니다. 그래서 O(log E) = O(log (V^2)) = O(log V)가 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/Algorithm</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/75</guid>
      <comments>https://jun9985.tistory.com/75#entry75comment</comments>
      <pubDate>Wed, 7 Feb 2024 19:19:24 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.29. ~ 2024.02.04.</title>
      <link>https://jun9985.tistory.com/74</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 21 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 31287 : 장난감 강아지 - S3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Simulation + Bruteforcing 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;min(N,K)번 반복시에 (0,0)으로 돌아오는 경우가 있는지를 알아보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 13076 : Distinct rational numbers - G1 [업다운 랜덤디펜스 성공! Solved - 11:08]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math + Euler Phi function 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a/b가 다른 경우의 수들을 구하라면 a,b가 서로 서로소인 경우들을 전부 더해주면 된다. 그리고 0도 포함해야하니 +1.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오일러 피 함수 문제를 오랜만에 봐서 다른 문제에 제출한거 가져다가 썼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 1854 : K번째 최단경로 찾기 - P4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dijkstra 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 각 노드가 i번째로 우선순위 큐에서 나왔다면 해당 경로의 길이가 i번째 최단경로이므로 최대 K번씩 우선순위 큐에서 나오도록 구현하면 되는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 13925 : 수열과 쿼리 13 - P1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lazy Segment Tree 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1,2번 쿼리만 보면 각 tr[n]은 결국 a*(tr[n])+b 형태로 업데이트가 되므로 덧셈용과 곱셈용 레이지 배열을 두 개 관리하면 되겠다는 생각이 바로 들었다. 그런데 3번 쿼리는 어떻게 계산해야할지 머리가 아팠는데, 저것도 레이지 배열로 해결할 수 있었다. 레이지 관리하는 것을 생각하고 구현하는데 머리가 매우 아팠던 문제.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 13550 : 수열과 쿼리 7 - D4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mo's + Sqrt Decomposition + Prefix Sum 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수열과 쿼리 0과 아에 동일한 문제. 차이는 mod K를 씌워주냐 마냐의 차이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 걍 수열과 쿼리 0 코드 가져다가 복붙하고 좀 수정해서 제출했다. (풀이 방법도 동일한 아이디어를 사용한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 메모리초과 문제로 계속 고통받아서 처음으로 stl의 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;deque 대신에&lt;span&gt; &lt;/span&gt;&lt;/span&gt;list를 써보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리를 줄일려면 list를 대신 쓰는것도 좋다는 걸 처음 알게 된 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. BOJ 2842 : 집배원 한상덕 - P4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Parametric Search + BFS로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피로도를 parameter로 두어 이분탐색을 박으면 된다. 고도값 개수가 최대 N*N개가 있는데 각 값을 최솟값이라고 두었을 때, 가능한 최댓값도 구할 수 있다. 이를 기준으로 BFS를 돌렸을 때 모든 집들을 들릴 수 있는지를 파악하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 시간복잡도는 O(N^4 log (1'000'000))에 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 정해는 Two-pointer로 푸는 것 같긴 하다. Two-pointer 연습을 더 하긴 해야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ 31395 : 정렬된 연속한 부분수열의 개수 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Math + Combinatorics 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A[i...j]까지 정렬이 되어있으면 가능한 조합은 (j-i+2) * (j-i+1) / 2개가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 j+1부터 정렬이 되어있는 조합을 또 찾으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도는 O(N)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. BOJ 13925 : 수열과 쿼리 13 - P1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lazy Segment Tree 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;식을 Ax+B로 표현이 가능하므로 이를 레이지 배열을 활용해서 풀 수 있긴하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 레이지 배열을 어떻게 구현하는가랑 1,2번 쿼리가 맞물릴 때, 3번 쿼리가 들어온 후에 1,2번 쿼리가 들어왔을 때 등을 고려하는게 어려웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. BOJ 13510 : 트리와 쿼리 1 - P1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HLD + Segment Tree 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a - b간의 간선을 a - e - b 이렇게 한 정점으로 표현하면 간선의 가중치를 정점의 가중치로 치환이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 HLD로 트리를 구간들로 쪼갠 후, Segment Tree를 활용해서 간선에 해당되는 정점을 업데이트 및 구간의 max값을 구하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요새 내가 알고리즘들을 직접 클래스나 함수로 구현해서 모듈화하는 작업을 해보고 있는데, 테스트 용도로 쓰기 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10 ~ 21. B5~4 문제들도 풀긴 했는데, 다들 비슷비슷해서 생략함. (이제 브론즈는 특별한 이유가 없는 한 일지에는 기록하지 않을 예정임.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 1000솔을 넘겼다. 다음은 1500솔을 바라보고 계속해보자.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/74</guid>
      <comments>https://jun9985.tistory.com/74#entry74comment</comments>
      <pubDate>Tue, 6 Feb 2024 17:48:52 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.22. ~ 2024.01.28.</title>
      <link>https://jun9985.tistory.com/73</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 14 문제.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;1. BOJ 14588 : Line Friends (Small) - G5&amp;nbsp;&lt;br /&gt;Floyd-Warshall 문제.&lt;br /&gt;각 선분에 대해서 겹치면 1로 두고, 이후에 Floyd-Warshall 실행.&lt;br /&gt;그러면 각 쿼리별로 O(1)만에 대답 가능하니 총 시간복잡도는 O(N^3+Q)가 된다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;2. BOJ 1525 : 퍼즐 - G2&lt;br /&gt;BFS + Tree Set / Hash Set 문제.&lt;br /&gt;메모리 제한 때문에 보드의 상태를 최대한 효율적으로 표현해야 했는데, 각 보드의 상태를 9자리 수로 표현함으로써 해결하였다. (예 : [[1,2,3],[4,5,6],[7,0,8]] -&amp;gt; 123456708)&lt;br /&gt;이후에 BFS를 돌리면 되는데, visited 배열은 tree_set이나 hash_set을 써서 하면 된다.&lt;br /&gt;나는 메모리 제한이랑 해시 충돌이 걱정되어 tree_set으로 구현하긴 했다. (나도 정확한 이유는 모르는데, hash_set은 터지는데 tree_set은 안 터지는 경우가 종종 있다. 아마도 tree_set은 겹치는 부분들은 무시하고, 필요시에만 노드를 생성하니 메모리를 좀 더 효율적으로 쓰는 것 같다.)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;3. BOJ 1253 : 좋다 - G4&lt;br /&gt;Sorting + Binary Search 문제.&lt;br /&gt;정렬을 했다면, 각 수를 기준으로 다른 수를 뺐을 때에 또 다른 수가 몇 개 있는지를 이분탐색으로 O(logN)에 찾을 수 있다.&lt;br /&gt;개수를 그렇게 세고 나머지 수가 기준이 되는 수와 같은지, 뺀 수와 같은지 경우의 수들을 계산해서 그걸 제외하고도 남는 수가 있는지를&amp;nbsp; 확인하면 된다.&lt;br /&gt;재밌게도 hash_map으로도 풀린다. (근데 거의 시간초과가 날 뻔 했음;;)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;4. BOJ 17499 : 수열과 시프트 쿼리 - S3&lt;br /&gt;Math 문제.&lt;br /&gt;수열이 시작하는 index를 앞뒤로 왔다갔다 하면 된다.&lt;br /&gt;그리고 1번 쿼리에서는 시작하는 index로부터 i-1번째로 떨어져 있는 수에 더해주면 되는데 modulo N을 해줘야 한다.&lt;br /&gt;간단한 수학 + 구현 문제.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;5. BOJ 24883 : 자동완성 - B5&lt;br /&gt;깡구현 문제. 스트릭 유지용으로 풀었다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;6. BOJ 8462 : 배열의 힘 - P2&lt;br /&gt;Mo's Algorithm 문제.&lt;br /&gt;모스 알고리즘 연습문제로, 수열과 쿼리 5나 6에서 쓴 것처럼 개수를 하나 씩 더하거나 빼면서 현재 답을 계속 고쳐나가주면 된다.&lt;br /&gt;모스 알고리즘을 알고 있다면 그리 어렵지는 않는 문제였고, 나도 내가 만들고 있는 알고리즘 라이브러리 테스트용으로 풀어보았다. (잘 돌아가서 다행이다.)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;7. BOJ 13546 : 수열과 쿼리 4 - D4&lt;br /&gt;Mo's Algorithm + Sqrt Decomposition 문제.&lt;br /&gt;같은 값에 대해서 구간 내에 제일 앞에 있는 것과 뒤에 있는 것의 거리를 구했을 때 그 중에서 최댓값을 고르는 문제였는데,&lt;br /&gt;일단 각 값에 대해서 구하는 건 쉽게 deque로 구현하면 되겠다는 생각을 했다.&lt;br /&gt;이후에 최댓값 고르는건 multiset이나 priority queue로 구해볼려 했는데 전부 TLE 떠서 해설을 보았다.&lt;br /&gt;최댓값 고르는 테크닉은 차이가 0 ~ N-1 사이이므로, 해당 차이만큼 나는게 몇 개가 있는지 배열을 만들기 + Sqrt Decomposition으로 각 쿼리별로 이동이 끝나고 O(sqrt(N)) 만에 구할 수 있어서 흥미로웠다.&amp;nbsp;&lt;br /&gt;(꽤나 유용해 보이는 테크닉이다.)&lt;br /&gt;그 와중에 pop_back과 push_front를 잘못 적어서 런타임 에러만 10번정도 떴었다. (이건 좀 심각한데;;;)&lt;br /&gt;어쨌든 이걸로도 Mo's 라이브러리는 체크했고, 영역을 넓히는 걸 우선적으로 하도록 코드를 수정할 수 있었다. (이 문제에서는 그렇게 안 하면 런타임 에러가 났었다...!)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;8. BOJ 13545 : 수열과 쿼리 0 - D4&lt;br /&gt;Mo's Algorithm + Sqrt Decomposition + Prefix Sum 문제.&lt;br /&gt;연속된 부분 수열의 합이 0인 것들 중 최대 길이를 구하라는 문제인데,&lt;br /&gt;이걸 Prefix Sum으로 전처리 하면 수열과 쿼리 4와 동일한 문제가 된다.&amp;nbsp;&lt;br /&gt;BOJ 13546를 풀고나서 푸니깐 그리 어렵지 않게 풀 수 있었다.&lt;br /&gt;만약 BOJ 13546를 안 풀었다면 누적 합으로 문제를 다르게 바꾸는 아이디어는 바로 못 떠올렸을 것 같긴 하다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;9. BOJ 17410 : 수열과 쿼리 1.5 - D5&lt;br /&gt;나는 Sqrt Decomposition + Segment Tree로 풀었다.&lt;br /&gt;정해는 Sqrt Decomposition만 가지고 조지는 거라는데, 나는 일단 Segment Tree를 쓰는 O(Qsqrt(N)log(10000)) 풀이가 떠올라서, 그렇게 구현했다.&lt;br /&gt;처음에는 TLE가 나오긴 했는데, 세그먼트 트리를 비재귀로 바뀌니 좀 더 뒤에서 TLE가 나왔어서 해당 풀이를 붙잡고 풀기 시작했다.&lt;br /&gt;세그 크기도 줄이면 매우 도움이 될것 같아서 원래 크기 4*N에서 2^x 꼴로 직접 수를 찾아서 바꿔주었고, Cache hit를 고려했을 때 더 빠를 것 같아서 배열 순서도 바꿔주었다. 이후에 상수 커팅 최적화 용으로 컴파일러 최적화도 명시할 수 있다길래 그것도 붙여보았다. 제출해보니 640ms로 AC를 받았는데, 70번째로 빨랐다. (물론 메모리는 더럽게 많이 먹긴 했다...)&lt;br /&gt;빠른것도 있지만 무엇보다도 D5 자력솔을 했어서 너무 기분이 좋았다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;10. BOJ 2098 : 외판원 순회 - G1&lt;br /&gt;Bit DP 문제.&lt;br /&gt;Bit DP 웰노운 문제인데, 이제야 풀어보았다.&lt;br /&gt;메모이제이션으로 푸는 방법을 알아내어 풀었으니 이제 응용 문제들을 풀어서 익숙해지면 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11. BOJ 1027 : 고층건물 - G4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforcing + Geometry 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 O(N^3)으로 양 점 사이에 끼어드는 건물이 존재하는지를 기울기로 판단하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;j &amp;lt; k&amp;lt; i 인 경우에 (h[i]-h[j]) / (i-j) &amp;gt;= (h[i]-h[k]) / (i-k)를 만족하면 겹치는게 존재하고, 하나도 안 겹치면 i와 j번째 건물은 서로 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실수 오차는 그냥 밑변을 양쪽에 곱해주어,&amp;nbsp; (h[i]-h[j]) * (i-k) &amp;gt;= (h[i]-h[k]) * (i-j)로 식을 바꿔주어 풀면 된다. 그러면 정수형으로도 충분히 풀 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실수 오차를 고려해서 식 정리하는 테크닉을 제외하고는 그리 어렵지 않는데 왜 G4까지 준지를 모르겠던 문제. 그래서 S1로 기여해두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12. BOJ 13322 : 접두사 배열 - B1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ad hoc 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접두사의 접두사는 항상 사전순으로 더 빠를 수밖에 없다. (앞에서부터 철자가 항상 똑같아서 결국 누구의 길이가 더 긴지만으로 판단된다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 그냥 0부터 |S|-1까지 순서대로 출력하면 되는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;13. BOJ 2877 : 4와 7 - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수학 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4와 7을 0과 1로 이진수표기가 가능하다. 그러면 몇 자리로 표현해야하는지를 찾고, 이에 따라서 K는 어떤 수가 되는지를 찾으면 된다. O(logK)만에 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;14. BOJ 31288 : 캬루 - S2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수학(정수론) + Ad hoc + Constructive 문제.&lt;br /&gt;일단 2자리 수 이상인 경우에는 홀수가 자명하므로, 모든 자리에서 어느 수를 특정 수로 바꿔서 3의 배수로 만들 수가 있다. 1자리 수라면 그냥 6같은 합성수로 바꿔주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코포스러웠던 문제.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;요새 태그 예측하는 감이 매우 떨어진다.&lt;br /&gt;특히나 애드혹, 매개변수탐색, 구현, 시뮬레이션 같은 태그들을 예측할 때 남발하고 있는데... 그 부분은 좀 더 고쳐야겠다.&lt;br /&gt;이번주 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/73</guid>
      <comments>https://jun9985.tistory.com/73#entry73comment</comments>
      <pubDate>Mon, 29 Jan 2024 23:46:21 +0900</pubDate>
    </item>
    <item>
      <title>제 3회 보라매컵 예선 Open Contest 후기</title>
      <link>https://jun9985.tistory.com/70</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2회 이후로 소식이 딱히 없던 보라매컵이 무사히 3회까지 열렸습니다! 솔직히 저는 2회 이후로 아무 소식도 못 받았어서 그냥 2회가 마지막일 줄 알았는데, 언제보니 홍보 탭에서 제 3회도 열린다고 하더라구요. 제 1회때는 실제 대회 참가자로써, 제 2회는 운영진으로써, 그리고 이번 제 3회때는 오픈컨테스트 참가자로써 개근하게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이번 대회 예선도 지난번 대회와 동일하게 서브태스크 문제들로 출제했습니다. 서브태스크 문제들만 출제했다는 뜻은 전체적인 문제 난이도 분포가 상당히 어려울 것일거라 예상했었습니다. 그래서 이틀동안 진행되는 실제 대회에서는 문제들을 효율적으로 잘 긁어 부분점수들을 최대한 따가는게 본선을 가기 위한 전략이었을 것이라 예상했습니다. (일단 저라면 저렇게 예선을 참가했을 것 같아요.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 저는 이번 대회를 실제 대회 참가자처럼 '효율적으로 잘 긁어서 순위권에 올라가보자!'라는 마인드로 참가했었습니다. 왜냐하면 제가 섭테 문제들만 존재하는 대회를 그리 많이 참가해보지 못해서 이 참에 연습하고자 했었습니다. 그리고&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이렇게 연습하다보면 HackerCup이나 SCPC 등 부분 점수가 있는 대회에서도 좋은 결과를 볼 수 있을거라고도 생각했구요.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;점수를 제일 효율적으로 긁어본다는 마인드로 참가한 결과는 아래와 같았습니다. 이제부터는 문제 순서대로 어떻게 풀었는지 후기를 남기도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1778&quot; data-origin-height=&quot;94&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k989S/btsDHqAMhgs/IBtjnjv6P1aambwzO8y38K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k989S/btsDHqAMhgs/IBtjnjv6P1aambwzO8y38K/img.png&quot; data-alt=&quot;제 3회 보라매컵 예선 결과입니다. 대회에서 총 3등으로 마무리 했었습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k989S/btsDHqAMhgs/IBtjnjv6P1aambwzO8y38K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk989S%2FbtsDHqAMhgs%2FIBtjnjv6P1aambwzO8y38K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1778&quot; height=&quot;94&quot; data-origin-width=&quot;1778&quot; data-origin-height=&quot;94&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;제 3회 보라매컵 예선 결과입니다. 대회에서 총 3등으로 마무리 했었습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;1. A번 : 대한민국을 지키는 가장 긴 힘 (+5) - 100/100&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;저는 &lt;b&gt;DP&lt;/b&gt;로 풀었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;대회가 있는 날이 제 동생 생일이기도 해서 외식하느라 처음에는 폰코딩으로 참가했었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;일단 제일 머리에 떠오른 생각은 첫 글자부터 가능한만큼 순서대로 긁어보았을 때가 최적이 아닐까 생각했었습니다. 폰코딩이다보니 구현 실수로 1 WA를 상큼하게 적립하고 제대로 구현해보니 100점 만점에 64점을 얻었습니다. 결과를 보고 아무래도 다른 방법으로 푸는 문제인 것 같으니 일단 B번으로 넘어가서 B번을 먼저 풀었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이후에 생각을 해보니,&lt;b&gt; dp[i]를 i번째 숫자가 묶이는 수의 제일 앞자리 숫자&lt;/b&gt;일때, &lt;u&gt;dp[i+1] = min(dp[i+1], dp[i]+1), dp[i+2] = min(dp[i+2], dp[i]+1)을 만족하고, 세 자리 수까지 묶은 결과가 641 이하면은 dp[i+3] = min(dp[i+3], dp[i]+1)을 만족&lt;/u&gt;했었습니다. (물론 제일 앞자리 수가 0일수는 없어서 예외 처리도 해주어야 합니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그렇게 구현해두고 if 문 조건을 잘못 적어서 3번 2점만 받다가 고쳐서 성불했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;2. B번 : 사격 (+1) - 100/100&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;저는 &lt;b&gt;Binary Search + Simulation&lt;/b&gt;으로 풀었습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;문제를 보고 해석해보면 초기값이 크면 클수록 얻을 수 있는 점수도 커지게 됩니다. 따라서 &lt;u&gt;초기값에 대해서 최대로 얻을 수 있는 점수는 monotone한 관계&lt;/u&gt;를 가지므로 &lt;b&gt;Binary Search&lt;/b&gt;를 적용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;왜인지 모르게 예전에 제가 만든 BOJ 30205가 생각나는 문제였습니다. 그래서 그런지 정해를 쉽게 떠올릴 수 있었습니다. 그래도 제가 처음에는 폰코딩으로 제출해서 1 WA를 적립했었습니다. 컴퓨터 잡고 제대로 짜니 AC가 나왔습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;3. C번 : 훈련 (+6) - 66/100&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;좀 &lt;b&gt;변형된 Knapsack DP&lt;/b&gt;가 정해일 것이라 생각합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;일단 바로 Knapsack DP를 어떻게 적용해야할 지 몰랐지만 Subtask 2는 그냥 Knapsack DP을 구현하면 되므로 Subtask 2번까지 먼저 긁었습니다. 그와중의 구현 실수 등의 문제로 인해서 6번째 제출에서 제가 원하던 66점을 얻을 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그리고 일단 넘어가서 나중에 F번을 푼 다음에 다시 돌아와서 손을 대보았으나...&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt; 대회가 끝나서 제출을 못했었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 나중에 문제가 올라온 다음에 제가 마저 짜던 코드를 제출해보니 AC를 받긴 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변형된 Knapsack DP가 맞았네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;4. D번 : 축구 대회 (+0) - 10/200&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 문제는 &lt;b&gt;DP 아니면 Bruteforcing 문제&lt;/b&gt;일 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;바로 어떤 태그인지도 떠올리지를 못하여 일단 제일 쉬운 섭테만 긁고 빨리 넘어갔습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(그런데 대회 끝나고보니 저는 Subtask 2까지 긁은 줄 알았는데, Suibtask 1만 긁었네요... 엄;;;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Bruteforcing 문제라면 BOJ 27282랑 비슷하게 조건을 잘 따져서 경우의 수를 줄이는 테크닉을 활용하는 문제일 것이라 생각합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;5. E번 : 시간 외 근무 멈춰!!! (+1) - 28/200&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 문제는&lt;b&gt; Greedy / Binary Search + Sorting + Simulation 문제&lt;/b&gt;일 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;'시간 외 근무 멈춰' 문제는 1회부터 꾸준히 나오는 문제였는데, 이 문제 시리즈의 기본적인 아이디어는 Greedy + Sorting 이었습니다. 그리고 이번 문제도 실제로 Greedy + Sorting 냄새가 나는 문제였습니다. 그런데 구현하는게 바로 떠오르지 않아 시간이 지체될 것이라 예상했습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래도 Subtask 2까지는 제 1회 문제랑 동일한 코드를 제출해도 풀리겠다는 생각이 들어서 일단 BOJ 27112 코드를 들고와서 수정해서 제출하니 Subtask 2까지는 긁혀 28점을 얻었습니다. 그러고 일단 F번을 풀러 갔습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;6. F번 : 물자 조달 (+6) - 300 / 300&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;저는 &lt;b&gt;Offline Query + Floyd-Warshall + 정점 분할&lt;/b&gt;로 풀었습니다. (실제로는 &lt;b&gt;Floyd-Warshall 응용&lt;/b&gt;입니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;일단 저는 대회를 시작하자마자 문제들을 전부 훑어보았습니다. 그때 이 문제의 제한조건을 잘못 이해해서 그래프의 구조가 트리인줄 알았습니다. 또한 문제에서 물어보는 것은 중간에 각 노드의 weight가 달라질 때 두 노드 간의 거리를 묻는 것이었습니다. 그래서 저는 처음에 이 문제가 HLD + Segment Tree로 쉽게 풀릴거라 생각했었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 앞의 C,D,E를 긁기만 하고 왔는데... 보니깐 그래프는 일반 그래프였습니다. 그래도 일단 &lt;u&gt;N의 조건이 작으므로 &lt;b&gt;Floyd-Warshall&lt;/b&gt;을 활용하는 것은 확실&lt;/u&gt;해 보였습니다. 그래서 충분히 긁은 것 같은 C번, DP인지 Bruteforcing인지도 모르는 D번과 구현에서 감이 잘 안오는 E번을 제치고 먼저 F번을 풀기로 했습니다. (그리고 F번을 풀면 당시에 퍼솔도 가능했어서... 퍼솔이 고팠어요...)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;먼저 Floyd-Warshall로 푼다면 어떻게 풀지 생각해보았습니다. 일단 &lt;u&gt;각 정점별로도 가중치&lt;/u&gt;가 주어지는데, 이는 &lt;b&gt;각 정점을 들오는 정점과 나가는 정점으로 분할&lt;/b&gt;을 해서 해소해야 될 것 같았습니다. 그리고 이제 두 정점을 이을 때는 나가는 정점 -&amp;gt; 들어오는 정점 이렇게 이어주면 될 것 같았습니다. 이후의 &lt;u&gt;두 정점에 대한 최단거리는 &lt;b&gt;Floyd-Warshall&lt;/b&gt;을 활용&lt;/u&gt;해서 찾았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이후에는 각 쿼리가 실행될수록 정점에 부하되는 가중치 값이 커져서 최단거리 값이 계속 커지므로 &lt;u&gt;쿼리 순서들을 뒤집어 계속 가중치가 줄어드는 방향으로 계산&lt;/u&gt;하면 되겠다는 생각이 들었습니다. 만약에 &lt;b&gt;&lt;u&gt;특정 노드(A라고 합시다.)에 부가되는 가중치가 계속 줄어든다면 각 노드간의 최단거리는 원래 값이나 아니면 A를 거쳐서 가는 경로의 거리 둘 중의 하나&lt;/u&gt;&lt;/b&gt;가 됩니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 &lt;u&gt;1번 쿼리가 들어오면 Floyd-Warshall을 개량해 O(N^2)로 업데이트&lt;/u&gt;를 해주었는데... O(QN^2)는 시간초과가 납니다. 그래서 제가 제출해보니 Subtask 2만 맞았었습니다. 이렇게 짜서 제출한 이유는 제가 또 조건을 잘못 읽었기 때문인데, 저는 각 기지별로 한 번씩만 공격하는 줄 알았는데 그게 아니라 특정 기지를 계속 공격하다가 타겟이 바뀌게 된다면 해당 기지는 다시 공격하지 않는다는 것이었습니다. (그래서 저는 Subtask 3번의 조건이 이해가 안 됐었습니다.) 만약에 기지마다 한 번씩만 공격한다면 모든 쿼리들을 실행 시켰을 때에 1번 쿼리에 대한 시간복잡도는 O(N^3)이라 뚫렸을 겁니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 저는 쿼리들을 역으로 처리하면서 &lt;b&gt;&lt;u&gt;공격하는 기지가 바뀌면 그때만 변형된 Floyd-Warshall로 업데이트, 아니면 평상시에는 현재 계산된 최단거리 vs 현재 공격하는 기지를 거쳐서 가는 거리를 계산&lt;/u&gt;&lt;/b&gt;해서 2번 쿼리에 대한 답을 구하는 식으로 구현했습니다. 그렇게 되면 &lt;u&gt;모든 쿼리들을 처리하는 시간복잡도도 &lt;b&gt;O(Q + N^3)&lt;/b&gt;&lt;/u&gt;이 됩니다. 그렇게 해서 제출하니 AC를 받았습니다. 그런데 스코어보드는 이미 프리즈된 상태라서 제가 퍼솔인지도 몰랐습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;나중에 대회가 끝나고나서 제가 F번을 퍼솔했다는 것을 알게 되었습니다. 한 번도 못 해본 퍼솔을 보라매컵에서 그것도 제일 어려운 문제에서 해서 매우 기뻤습니다. 다만, 제가 이 대회에서 조건이나 지문을 제대로 안 봐서 WA를 맞는 등 기초적인 실수도 많이 있어서 그 점들은 반성해야 하겠습니다. 참가자 입장으로써 문제 퀄리티도 괜찮아 재밌게 풀었습니다. 특히나 DP를 좋아하면 매우 재밌었을 것 같아요. (무려 6문제들 중 3문제(A,C,F)가 DP...!)&lt;/span&gt;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/대회 후기</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/70</guid>
      <comments>https://jun9985.tistory.com/70#entry70comment</comments>
      <pubDate>Mon, 22 Jan 2024 21:16:03 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.15. ~ 2024.01.21.</title>
      <link>https://jun9985.tistory.com/69</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 블로그에 일지만 올리니까 블로그 자체가 내 PS 기록으로만 가득찰 것 같아 매일 마다 적어두고 일 주에 한 번씩 올리려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;s&gt;사실 매일마다 올리기 귀찮아서;;&lt;/s&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 10 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 27903 인생 - Unrated&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Golfscript로 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핸들 때문에 printf, print, cout 등등이 다 막혀서 매우 막막했던 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 핸들에 따라서 난이도가 천지차이가 나므로 이건 아무리 생각해도 Unrated 문제가 맞다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(만약 백준 핸들이 aaaaaa 이런식이면 파이썬으로도 쉽게 풀 수 있다... print(chr(97)+...) 이런식으로)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 15912 우주선 만들기 - G3 &amp;nbsp;[업다운 랜덤디펜스 성공! Solved - 20: 42]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP + PQ / Tree Set로 푼 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP[i]를 i번째 부품까지 살 때에 최솟값, MAX_W[j...i] 및 MAX_E[j...i]를 각각 j ~ i 부품들 중에 최대 W 및 E값이라 하면 아래와 같은 식을 세울 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP[i] = min(DP[i], DP[j] + MAX_W[j+1...i] * MAX_E[j+1...i], MAX_W[1...i] * MAX_E[1...i]) (1 &amp;lt; j &amp;lt; i)&lt;br /&gt;그래서 MAX_W[j+1...i] 및 MAX_E[j+1...i]를 구하기 위해서 multiset을 활용해 구했는데... 나중에 생각해보니 PQ도 굳이 필요가 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 맞춘 후에 PQ / Tree Set 없이 다시 풀어보니 0ms 로 답이 잘 나왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 2749 피보나치 수 3 - G2 [업다운 랜덤디펜스 성공! Solved - 05:37]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할정복을 활용해서 행렬 제곱을 하는 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A = [[1,1],[1,0]]라면 A^N한 결과 B에서 B[1][1]이 답이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 유명하고 이미 아는 유형이여서 쉽게 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. BOJ 19643 좀비 떼가 전역 때보다 먼저 오다니 - P3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백트래킹 + 휴리스틱 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백트래킹 문제 같이 보이긴 했는데 이걸 나름 계속 커팅했어도 계속 TLE 나길래 DP인가 살짝 기웃거렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 DP로도 이거 못 풀 것 같아서 태그를 확인했는데... 휴리스택 태그 붙은 거 보고 뒷머리를 잡았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국에 아래 조건들을 붙여서 커팅을 해서 풀었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;B1_power &amp;gt;= B2_power 라면 굳이 B2는 고려할 필요 없다.&lt;/li&gt;
&lt;li&gt;B3은 업데이트 범위가 O(L)이므로 현재 맨 앞에 있는 좀비를 꼭 죽여야 하는 상황인데 B3로 못 죽이면 볼 필요가 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;난 그저 그냥 BOJ 19644 푼게 기억나서 본건데... 왜 정답률이 10%에 머무르고 있는지 알 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커팅 기술을 통해서 최적화하는건 나도 삼성 알고리즘 특강하면서 매우 흥미로운 주제라고는 생각하는데, 이 문제는 아에 이런식으로 커팅하는게 정해여서 난이도를 기여하지 않았다. 내가 제출한 풀이보다 더 빠른 풀이들이 존재하는 걸 보면 이게 정해는 아닌것 같은데... 에디토리얼이 인터넷에 뒤져도 안 나오니 원;;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. BOJ 1117 : 색칠 1 - G5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수학 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;f &amp;lt;= W-f 라는 가정하에서 설명해보도록 하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;색칠이 끝나고 다 펴보면 f 기준으로 오른쪽은 접은 상태에서 색칠한 칸의 개수 * (c+1)개가 색칠되어 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽은 색칠된 칸의 개수가 같거나 더 적을 수 있는데, 왼쪽과 맞닿은 칸들의 개수를 따로 계산해서 이에 c+1을 곱해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이 둘을 합치면 총 색칠된 칸의 개수가 되니 답을 쉽게 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 f &amp;gt; W-f 면 그냥 오른쪽과 왼쪽의 케이스가 서로 바뀐거라 그냥 f대신에 W-f를 기준으로 접어서 풀어도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;G5 ~ G3 랜덤디펜스를 하려다가 찾은 문제. 시간은 제대로 재보지는 않았지만 한 10~20분 내로 푼 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. BOJ 14925 : 목장 건설하기 - G4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP + Prefix Sum 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행렬 내에서 제일 큰 정사각형 크기를 찾는 문제. (i,j)&amp;nbsp; 좌표에 대해서 최대 크기가 S라면 (i-1,j), (i, j-1), (i-1,j-1) 에 대해서는 최대 크기가 S-1 이상이어야 한다. 따라서, dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])을 만족하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웰노운 DP 문제로 2D Prefix Sum 기본 문제라 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ 1915 : 가장 큰 정사각형 - G4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;DP + Prefix Sum 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 변의 크기가 아니라 넓이를 출력하는 것 제외하고는 BOJ 14925랑 동일하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기여창에 같은 문제라길래 같이 풀었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[제 3회 보라매컵 예선 Open Contest] - 3 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8 ~ 10. 이 문제들은 나중에 예선 오픈 콘테스트 후기 남기면서 다뤄볼 예정.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 F번을 내가 퍼솔 먹어서 너무 행복했다 ㄹㅇㅋㅋ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1778&quot; data-origin-height=&quot;94&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wvj8H/btsDJU1VzYr/rCQUwGcMpUDk3bQ0urGBuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wvj8H/btsDJU1VzYr/rCQUwGcMpUDk3bQ0urGBuk/img.png&quot; data-alt=&quot;마지막 F번 퍼솔 및 300점이라는 점수로 3등까지 달성한 나&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wvj8H/btsDJU1VzYr/rCQUwGcMpUDk3bQ0urGBuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwvj8H%2FbtsDJU1VzYr%2FrCQUwGcMpUDk3bQ0urGBuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1778&quot; height=&quot;94&quot; data-origin-width=&quot;1778&quot; data-origin-height=&quot;94&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마지막 F번 퍼솔 및 300점이라는 점수로 3등까지 달성한 나&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/69</guid>
      <comments>https://jun9985.tistory.com/69#entry69comment</comments>
      <pubDate>Sun, 21 Jan 2024 21:31:33 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.14.</title>
      <link>https://jun9985.tistory.com/66</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 15571 : 블록 3 - G2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP + Sliding Window 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 오늘 프로젝트 회의를 해야했는데 딱히 공유할 내용이 없어서, 같이 플젝하는 동생이 막힌 문제를 풀어보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단, 난 처음에 수학이나 DP일 것 같기는 했는데, O(NM)은 터지니깐 어떻게 풀 지를 몰랐으나 같이 플젝하는 동생이 고민했던 결론들 가지고 빠르게 답을 도출할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;슬라이딩 윈도우를 활용해서 O(M)만에 풀 수 있으며, 아는 동생의 말에 따르면 행렬로도 풀리는 것 같다고 하는데, 저게 된다면 O(logM) 만에도 가능할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/66</guid>
      <comments>https://jun9985.tistory.com/66#entry66comment</comments>
      <pubDate>Sun, 14 Jan 2024 23:50:45 +0900</pubDate>
    </item>
    <item>
      <title>2023 경인지역 6개 대학 연합 프로그래밍 경시대회 shake! Open Contest 후기</title>
      <link>https://jun9985.tistory.com/65</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요새 계속 스트릭 유지를 위해서 별로 어렵지 않는 문제들만 풀어보다가 CP 실력도 죽은게 아닌가 싶기도 하고 마침 시간도 나서 2023년 shake! 대회에 참가해보았습니다. 아레나 등록하고 참가해보았는데, 제가 여태까지 해본 아레나 중에서 제일 어려웠던 것 같습니다. 특히나 난이도 순서대로 배치된게 아니라 랜덤으로 배치되어서 어느 문제가 쉬운지 파악하는데 좀 애를 먹었던 것 같습니다. (그래서 그냥 스코어보드 보고 몰리는데로 따라갔긴 했습니다.) 이제부터 시간 순대로 어떤 문제들을 풀어보았는지 후기를 남기도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;75&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5agSt/btsDuyRrLVX/GtO01lkxGxm6pj9nBJ3xY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5agSt/btsDuyRrLVX/GtO01lkxGxm6pj9nBJ3xY1/img.png&quot; data-alt=&quot;2023 경인지역 6개 대학 연합 프로그래밍 경시대회 shake! 결과입니다. 아레나에서는 총 13등으로 마무리, 오픈컨에서는 총 21등으로 마무리 했었습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5agSt/btsDuyRrLVX/GtO01lkxGxm6pj9nBJ3xY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5agSt%2FbtsDuyRrLVX%2FGtO01lkxGxm6pj9nBJ3xY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1608&quot; height=&quot;75&quot; data-origin-width=&quot;1608&quot; data-origin-height=&quot;75&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2023 경인지역 6개 대학 연합 프로그래밍 경시대회 shake! 결과입니다. 아레나에서는 총 13등으로 마무리, 오픈컨에서는 총 21등으로 마무리 했었습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. C번 : 또 수열 문제야 (+1)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Ad-hoc + Constructive&lt;/b&gt; 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 스코어보드에서 제일 빠르게 정답이 나와서 별 생각없이 '제곱수만 다 넣어도 괜찮지 않을까?'라고 생각하여 상큼하게 1 WA를 받고 시작했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 &lt;b&gt;'소수에서 ab % (a+b) == 0은 나올 수 없겠다.'&lt;/b&gt; 라 판단하여 N개의 소수들을 순서대로 출력하여 AC를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데, 나중에 디스코드방에서 그냥 &lt;b&gt;홀수들만 출력하면 되는 문제&lt;/b&gt;였다길래 오버킬을 했구나 싶었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*여담으로 소수에서 ab % (a+b) == 0 이 나올수 없다는 이유는 다음과 같았습니다. a,b는 서로소이며 소수입니다. 따라서 소인수분해 결과에 따라서 ab는 약수가 1, a, b, ab 밖에 없습니다. 그 와중에, a &amp;gt; 1, b &amp;gt; 1 이므로 ab = a+b인 경우만 조심하면 되는데, b로 나눠보면 a = a/b+1 꼴이 됩니다. 그런데, a는 자연수이고, a와 b가 서로소인 관계로 a/b는 자연수가 아닌 유리수가 되므로, ab = a+b 인 a,b는 존재할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. I번 : 올라올라 (+1)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Binary Search + Monotone Queue&lt;/b&gt;로 풀었긴 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;최소 k를 찾는 문제&lt;/u&gt;였어서 &lt;b&gt;Binary Search&lt;/b&gt;가 빠르게 떠올랐고, 이후에 &lt;u&gt;특정한 크기의 구간별로 최댓값을 찾는 문제&lt;/u&gt;라서 &lt;b&gt;Multi-set 아니면 필요시 Monotone Queue 테크닉&lt;/b&gt;도 써야한다는 판단을 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 사람들이 빠르게 풀었으니 Multi-set을 사용하는 풀이도 되겠지라는 마음에 써봤는데 1 TLE가 났어서, 급하게 예전에 구현해둔 Monotone Queue 테크닉 코드를 가져와서 고쳐서 AC를 받았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정해는 Greedy 아니면 Stack이라고 하던데 잘 모르겠습니다. (Greedy는 대강 코드를 보니 Two-pointer랑 섞어서 좀 더 쉽게 풀 수 있었나 보네요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. D번 : 모비스터디 (+0)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Dijkstra + 역추적&lt;/b&gt;으로 풀었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 문제에서 지시한대로 A에서 각 노드별로의 최단 거리를 구했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 B부터 순서대로 &lt;b&gt;현재 보고 있는 노드가 n이라면 dist[n] = dist[k] + cost[k]를 만족하는 k 노드를 다음에 보도록 BFS&lt;/b&gt;를 하였습니다. (이 과정 자체가 역추적이기도 하지요.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS를 하는 과정에서 탐색한 모든 노드들을 set에 담아두어 나중에 오름차순으로 출력하니 AC를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. B번 : 실 전화기 (+2)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;수학&lt;/b&gt; 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C를 풀고 손을 댔던 문제였는데, 그림을 몇 개 그리면서 별 생각없이 &lt;u&gt;'N, K가 서로소가 아니면 사이클이 생기므로 0이 답이고 아니면 min(N*(K-1), N*(N-K-1))이 답일 것&lt;/u&gt;이다'라는 판단을 하여 그렇게 짰습니다. 당연히 1 WA를 정립하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다가 D, I번이 스코어보드에 많이 AC를 받은게 보여서 두 문제를 풀고 다시 와서 이번에는 &lt;u&gt;&lt;b&gt;'N%min(K, N-K) == 0인 경우에만 답이 0&lt;/b&gt;&lt;/u&gt;이겠구나' 생각해서 그렇게 고치고 제출하니 2 WA도 적립하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 왜 틀렸는 가 싶어서 N = 10, K = 4인 예제를 그려보았는데,&lt;u&gt; &lt;b&gt;N과 K를 최대공약수로 나누어주고 min(N*(K-1), N*(N-K-1))을 구해야 하는 것&lt;/b&gt;&lt;/u&gt;을 알아서 고쳐서 AC를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. G번 : 관광 상품 (+0)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Ad-hoc&lt;/b&gt; 문제가 아니었나 싶습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 보다가 &lt;u&gt;'4개를 보았을 때 최대가 나온다면 2개로 보았을 때도 최대가 나올 수 있을 것이고, 5개를 보았을 때 최대가 나온다면 3개로 보았을 때도 최대가 나오지 않을까?&lt;/u&gt;'라는 생각을 해서 구현했는데 얻어 결렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 디스코드 방에서 알아보니 꽤 유명한 웰노운 문제였다고 합니다. 이건 제가 정해랑 증명을 이해하고 한 번 블로그에다가 정리해봐야 할 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. H번 : 대역폭 관리 (+1)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Heavy-Light Decomposition + Lazy Segment Tree&lt;/b&gt;로 풀었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 문제에서 제일 필요한 건 &lt;u&gt;사실상 경로에 속한 모든 노드들에 대해서 값을 업데이트&lt;/u&gt;를 해주어야 했는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 &lt;b&gt;&lt;u&gt;어떻게 구간으로 치환이 가능하다면 Lazy Segment Tree로 구할 수 있겠다&lt;/u&gt;&lt;/b&gt;는 생각이 들었습니다. 이게 가능하다면 해당 &lt;u&gt;&lt;b&gt;예약을 받으면 문제가 되는지 안 되는지도 업데이트가 될 구간에 대해서 minimum query를 날린 결과가 w보다 작은지 안 작은지로 판단&lt;/b&gt;&lt;/u&gt;이 될 테니 경로를 구간으로 치환만 해줄 수 있는 방법을 찾으면 되겠다는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 경로들을 어떻게 구간으로 바꿀까 생각했을 때 처음에는 Euler Tour Trick을 생각해보았는데, 제가 생각한 Euler Tour Trick을 활용한 해에서는 문제점들이 존재했습니다. 그래서 다른 방법들을 찾아 인터넷을 뒤져보니 Heavy-Light Decomposition을 활용하면 되겠다는 아이디어를 얻었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;Heavy-Light Decomposition&lt;/b&gt;은 Heavy한 간선들을 한 그룹으로 엮어서 경로상에 있는 노드들이 같은 그룹이라면 O(logN)만에 업데이트&lt;/u&gt; 할 수 있었습니다. 알고리즘 전체 원리를 제대로 파악은 하지 못했긴 했지만 대강 Square-root Decomposition 같이 구간들을 특정 크기만큼씩 쪼개어 시간복잡도를 줄이고, 또한 Smaller-To-Larger와 비슷한 원리로 light한 간선들을 탔을 때 크기가 2배 이상씩 늘어나니 O((logN)^2)만에 구간 업데이트가 가능하다고 파악했습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 &lt;a href=&quot;https://justicehui.github.io/hard-algorithm/2020/01/24/hld/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Heavy-Light Decomposition을 구현한 글&lt;/a&gt;을 참고해서 &lt;b&gt;Minimum Query를 날릴 수 있는 Lazy Segment Tree를 구현했고, 이를 HLD 코드와 잘 작동하도록 다듬어서 제출&lt;/b&gt;해보니 구현 실수해서 WA를 받았습니다. 이후에 디버깅해서 다시 제출해보니 AC를 받았습니다. 처음으로 HLD 문제를 이렇게 풀어보게 되어 감격스러웠으나... 정해는 LCA라고 합니다. (LCA 문제라고도 생각은 해보긴 했는데... 어떻게 풀어야 할지는 아무래도 아이디어가 안 떠오르네요...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지가 이번 대회에서 제가 푼 문제들이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에도 못 푼 문제들에 대해서도 대강 후기를 남겨보자면...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A번 :&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이 문제를 보자마자 BOJ &lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;27280 이기적인 목봉체조 (Easy) 문제가 생각났습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;O(M^2)만에 [k..j]에서의 제일 떨어진 두 점의 거리들을 모두 전처리해서 구할 수 있었고 이제 DP[N][K] = max(DP[N-1][j] + cost[j][k], DP[N][K])를 최적화하여 풀면 될텐데... 저 DP식을 어떻게 최적화 해야할지 몰라서 못 풀었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;짧은 식견으로나마 대충 예상해보면 Segment Tree를 활용해서 max 쿼리를 어떻게 날려서 저 DP 테이블을 모두 구하는데 O(NMlogM)만에 구할 수 있었지 않았을까 생각해봅니다. (마치 BOJ 27284 이기적인 목봉체조 (Hard)처럼 말이죠. 근데 사실 저는 저 문제도 못 풀었어서;;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;+) 그런데 이 글을 쓰고 있는 시점에서 정해는 O(5NM)이라는 걸 들었습니다. 이건 한 번 꼭 풀어보고 싶네요;;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;E번 :&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;뭔가 특정 룰에 따라서 구하면 되는 Ad-hoc 문제가 아니었을 까 생각합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;아니면 어느 조건에 따라서 그리디스럽게 구하면 되는 문제였든지요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;아무튼 이 문제를 보긴 했는데도 머릿속에서 해가 잘 떠오르지 못해서 그냥 런쳤습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;F번 :&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;일단 Tree 알고리즘을 쓰는 문제인 것 같긴 한데요... &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;Centroid-Decomposition 막 그런거 쓰는 문제가 아니었을까 생각해보긴 했습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;디코방에 올라오는 것 보니 Smaller-to-Larger 및 여러 테크닉들을 활용해서 푸는 문제였다고는 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;J번 :&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;기하 문제인 것을 파악한 순간 문제도 제대로 안 읽고 런쳤습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;기하는 너무나 무서워요...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;후기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요새 맨날 스트릭 유지용 문제들만 풀다보니 문제들을 보고 난이도 파악을 바로하는게 쉽지가 않았습니다. 또한, 오버킬을 해서 푼 문제들도 많아서 이런 부분들은 반성해야겠다는 생각이 들었습니다. 그래도 오랜만에 어려운 대회에 참가하게 되어 재밌었습니다. 그리고 이번 기회를 통해서 HLD를 써본 것도 매우 뜻 깊었던 대회라 생각이 듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 리뷰할 대회는 아마도 제 3회 보라매컵일 것 같습니다. 이번에는 저도 참가자 입장이라서 기대되네요 :)&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/대회 후기</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/65</guid>
      <comments>https://jun9985.tistory.com/65#entry65comment</comments>
      <pubDate>Sun, 14 Jan 2024 23:45:58 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.13.</title>
      <link>https://jun9985.tistory.com/64</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[2023 경인지역 6개 대학 연합 프로그래밍 경시대회 shake!] - 6 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 ~ 6. 문제 푼 후기는 나중에 따로 올릴 예정. 전반적으로 난이도가 있었다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ 31242 : ШАХМАТНА ДЪСКA - S5 (내가 기여)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 문제를 읽어보니 그냥 나이트의 움직임을 구현해서 시뮬레이션만 돌려도 되는 문제라고 판단하여 풀어보니 맞았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;난이도가 그리 있지는 않아 S5로 일단 기여하였다. 잘만하면 B1까지도 볼 수 있지 않을까 싶긴한데...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;암튼 BOJ 29698 합동 훈련에 이어서 내가 제일 처음으로 제출해 맞은 문제다 :)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;820&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRVrlO/btsDqRdajYD/Bz5qMWySHel4m0Bw881qu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRVrlO/btsDqRdajYD/Bz5qMWySHel4m0Bw881qu1/img.png&quot; data-alt=&quot;KIAAAAAA 뽕에 찬다 ㄹㅇㅋㅋ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRVrlO/btsDqRdajYD/Bz5qMWySHel4m0Bw881qu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRVrlO%2FbtsDqRdajYD%2FBz5qMWySHel4m0Bw881qu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;788&quot; height=&quot;820&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;820&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;KIAAAAAA 뽕에 찬다 ㄹㅇㅋㅋ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Codeforce Round 919 Div.2] - 2 solved.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 친 코포 라운드는 최악이었다. 레이팅 엄청 떨어질 것 같다 하...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. A번 &lt;a style=&quot;background-color: #f8f8f8; color: #0000cc; text-align: center;&quot; href=&quot;https://codeforces.com/contest/1920/problem/A&quot;&gt;Satisfying Constraints&lt;/a&gt; - (00:08)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 가능한 최대, 최소 범위를 찾고, 중간에 들어가면 안 되는 수들은 따로 저장하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에, 최대 - 최소 + 1 범위가 항상 가능하니 먼저 이렇게 계산하고, 안 되는 수들 중에서 최대랑 최소 범위 내에 있는 만큼 정답에서 차감하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. B번 &lt;a style=&quot;background-color: #ffffff; color: #0000cc; text-align: center;&quot; href=&quot;https://codeforces.com/contest/1920/problem/B&quot;&gt;Summation Game&lt;/a&gt; - (00:36)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bob은 남은 값들 중에 값이 큰 순서대로 최대 x개를 -1로 곱할 것이다. (다만 0 이상이면!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 먼저 Alice가 아무것도 안 건드렸을 때의 Bob이 최소로 하는 수를 구하고 거기서부터 Alice가 최댓값 하나씩 지울 때에 Bob이 새로운 값을 하나 더 -1로 곱하고... 이걸 K번까지를 모두 돌려보면서 나오는 답들 중에서 최댓값을 찾으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C번은 나중에 보니 정수론 지식이 필요한 문제였다. 합동식을 알아야 풀 수 있는 문제같은데 하... 수학은 너무나도 싫다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 오랜만에 PS를 많이해서 뿌듯하긴하다. 이제 자바스크립트 공부해야지...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/64</guid>
      <comments>https://jun9985.tistory.com/64#entry64comment</comments>
      <pubDate>Sun, 14 Jan 2024 02:23:44 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.12.</title>
      <link>https://jun9985.tistory.com/63</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 16394 홍익대학교 - B5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사칙연산 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 계산해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내일은 Arena 참가해서 다시 기강 잡아야지...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/63</guid>
      <comments>https://jun9985.tistory.com/63#entry63comment</comments>
      <pubDate>Sat, 13 Jan 2024 13:56:38 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.11.</title>
      <link>https://jun9985.tistory.com/62</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 2393 Rook - B5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텍스트 복붙하면 되는 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 한국으로 복귀하는 날이라 이 문제만 풀 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/62</guid>
      <comments>https://jun9985.tistory.com/62#entry62comment</comments>
      <pubDate>Fri, 12 Jan 2024 05:19:59 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.10.</title>
      <link>https://jun9985.tistory.com/61</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 6679 : 싱기한 네자리 숫자 - B2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브루트포스 + 구현 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;범위 내의 모든 숫자에 대해서 10, 12, 16진수로 표현했을 때 자리들의 합을 직접 계산하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도야 O(NlogN)이긴 한데, log 밑이 10, 12, 16이라서 매우 충분하게 돌아간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/61</guid>
      <comments>https://jun9985.tistory.com/61#entry61comment</comments>
      <pubDate>Thu, 11 Jan 2024 11:16:37 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.09.</title>
      <link>https://jun9985.tistory.com/60</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 27328 : &lt;span&gt;三方比較 (Three-Way Comparison)&lt;/span&gt;&amp;nbsp;- B5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스트릭용 구현 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a와 b를 비교하면 되는 간단한 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 말레이시아 인터넷 속도가 너무 느리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 10년전 인도네시아 인터넷 속도 같은데... 인도네시아도 여전할려나 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/60</guid>
      <comments>https://jun9985.tistory.com/60#entry60comment</comments>
      <pubDate>Wed, 10 Jan 2024 07:49:44 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.08.</title>
      <link>https://jun9985.tistory.com/59</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 2 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ &amp;nbsp;24082 &lt;span&gt;立方体 (Cube) &lt;/span&gt;- B5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사칙연산 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;받은 값을 세제곱한 값을 출력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대가 10^9이니깐 32-bit Integer로도 안 터질듯하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[랜덤디펜스] - G4부터 다시 시작.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 14502 연구소 - G4 (Solved - 13:52)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bruteforce + Flood-fill(BFS)문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N, M의 범위가 매우 작아서 모든 0 자리중 벽을 세울 세 자리 조합을 전부 돌려봐도 상관없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기둥을 세운 다음에는 BFS로 안전 영역을 계산하고, 그 중 최댓값을 고르면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어는 어렵지 않았는데, 구현이 좀 귀찮았다. &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/59</guid>
      <comments>https://jun9985.tistory.com/59#entry59comment</comments>
      <pubDate>Mon, 8 Jan 2024 10:54:51 +0900</pubDate>
    </item>
    <item>
      <title>2023년도 PS 회고록</title>
      <link>https://jun9985.tistory.com/58</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;작년 한 해는 많이 놀았던 것 같습니다. 군대에서 전역을 하고 6개월 동안 집에서 계속 PS를 하고, 교회 신앙생활이랑 요리도 배우고 좀 쉬어가는 느낌이었습니다. (물론 2년간 뺑이친 걸 생각하면 좀 더 놀고 싶어서 한 학기 더 휴학할 예정이긴 하지만요.) 그러다보니 올해는 PS 관련된 활동을 많이 했었기도 했고 PS가 많은 영향을 끼쳤던 것 같습니다. 이번 글에서는 이에 대해서 회고를 해보고자 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PS는 제가 군 생활을 하면서 후임 덕분에 시작했었는데요. 당시에는 그냥 '사무실 근무시간 녹이기 위해서 해볼까? 코테도 준비할겸 같이하지 뭐' 이런 생각으로 PS를 시작했던 것 같습니다. 저는 군대가기 전에는 학부연구생으로 2년 동안 AI만 공부했었는지라 PS에 대해서는 하나도 몰랐었습니다. 그리고 'PS는 걍 코테 뚫을려고 하는거 아닌가? 이게 도움이 될까?'라는 생각과 같이 PS를 열심히 하는 것에 대해서는 좀 시간낭비라는 생각이 들었습니다. 그래서 좀 하다가 말고 / 하다가 말고 이런 생활이 반복되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PS에 대해서 제가 깊게 파기 시작한 건 제작년 11월 쯤부터 그랬던 것 같습니다. 정확하게 어떤 계기로 그때부터 열심히 하게 된 건지는 기억이 잘 안 나는데, 아마 코드포스를 처음 보고나서부터 CP에 대한 관심도 생기고 PS를 열심히 시작했던것 같습니다. 그러면서 자연스레 실랜디도 되고, 골랜디도 어느정도는 되기 시작하고... 하다가 작년 6월에 전역하게 되었습니다. 전역을 한 후에는 대회들도 참가해서 팀으로도 같이 대회를 출전해보기도 하고, 백준에서 대회 출제자 및 운영자로 들어가서 아레나도 운영해보는 등 여러 PS 관련 활동들을 할 수 있었습니다. 제가 올해 PS 관련 활동들은 아래와 같이 정리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 현대 모비스 알고리즘 대회 - 예선 광탈&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. UCPC 대회 - 본선 진출, 44팀 중에서 24등으로 마무리.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 삼성 DX 알고리즘 하계 특강 - 수료 및 Pro 검정(B형) 취득함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 제 2회 보라매컵 - 예선 및 본선의 출제자로 참여, 총 4 문제 출제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. Meta Hacker Cup - Round 2에서 1,540등으로 마무리. 기념 티셔츠 획득.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. Codeforce - 블루 달성.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. BOJ &amp;amp; solved.ac - 다이아 달성.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. Softeer HSAT 8차 자격인증 - 취득함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중에서 기억이 많이 남는 활동은 UCPC 대회 참여, 삼성 알고리즘 특강 및 제 2회 보라매컵 출제한 것이었는데, 이에 대해서 좀 더 자세히 이야기하고 글을 마칠려 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. UCPC 대회&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 첫 팀 대회이자, 오프라인 PS 대회였습니다. 당시에 제가 코드포스 블루도 한 번 찍었던걸로 기억해서 CP는 어느정도 익숙하다고 생각했으나 팀 대회는 매우 달랐습니다. 특히나 본선 진출이 확정되고나서 당일치기로 서울에 올라가 팀원들과 같이 팀 연습을 하는 경험도 색달랐고, 실제 대회에서 대략 5시간 동안 계속 문제보고 팀원이랑 서로 이야기하면서 아이디어 공유하는 경험도 재밌었습니다. 이외에도 예선때 팀원들이 부대 내에 있는 상황이라 디스코드 채팅으로만 서로 이야기하면서 푼 것도 신기했습니다. 이 뒷북 글을 보게 될지는 모르겠지만 테라포밍UCPC 팀원분들 모두 고생했고 언제 서울에서 테라포밍마스 한 판 해요! (전역하고 이 게임이 이렇게 그리울줄은 몰랐네요 ㅠㅠ) 다시 한 번 팀으로 올해 UCPC 참여해도 좋구요 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 삼성 DX 알고리즘 하계 특강&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SWExpertAcademy의 문제들 특징상 구현이 매우 중요해서 구현을 매우 연습할 수 있던 기간이었습니다. 이외에도 교수님의 특강도 재밌었고, 삼전 건물에 들어가서 시험도 치는 것도 색달랐습니다.(그리고 화장실 디자인이 매우 예쁘다고 들었는데, 실제로 디자인이 예쁘더라구요 ㅎㄷㄷ)&amp;nbsp; 그것말고도 이 특강을 하면서 O(logN) LCA 및 Lazy Segment Tree 구현도 익힐 수 있었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 제 2회 보라매컵&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 출제하는 건 매우 색다른 경험이었습니다. 항상 문제를 풀기만 하던 입장에서 출제를 처음해보았는데, 문제를 하나 출제하기까지 이렇게 여러 단계들이 있는지는 처음 알았습니다. 난생 처음보는 testlib.h도 다뤄서 generator도 만들어보고, edge 케이스 관련해서 직접 테케도 만들어보고, 문제 아이디어를 가지고 이에 알맞는 지문을 작성하고, 다른 출제진의 문제도 검수해서 피드백도 주고... 이렇게 많은 과정을 거쳐야 문제가 나오는줄은 몰랐습니다. 처음 출제하는 입장에서 저는 처음에는 약간 헤매었지만 다행이 운영진 및 검수진 분들의 도움을 받아서 성공적으로 문제를 출제할 수 있었습니다. (특히나 지문 부분에서 처음에 제가 작성한 것보다 훨씬 나아지는 마법을 보았습니다.) 4 문제를 준비하느라 나름 힘들었었고 대회랑 오픈 컨테스트(특히나 아레나 였던 본선)에서 제발 문제가 없기를 마음 졸이면서 맘고생도 했었지만, 끝나고 나니 문제를 출제해보았다는 사실에 매우 뿌듯했습니다. 그리고 다들 꽤 좋은 평가를 주어 한동안 문제 기여창만 계속 보면서 행복했었습니다. 이것도 한참 뒷북이라 볼지는 모르겠지만 운영진 및 검수진 분들 매우 고생하셨습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 마지막으로 제가 출제한 문제들을 소개하면서 글을 마치도록 하겠습니다. 각각마다 TMI도 같이 달아둘게요 :)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/29695&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 29695 기지방호&lt;/a&gt; - G1
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예선 C번 문제.&lt;/li&gt;
&lt;li&gt;이 문제는 아주 예전부터 구상해왔던 문제긴합니다. 다만, 당시에 생각했을 때는 TSP DP로 푸는 문제였어서 반려당했습니다. 그래서 해당 문제의 컨셉을 지키면서 어떻게 다르게 낼 수 있을까 생각하며 산책하다가 우연히 '플로이드-워셜을 이렇게 꼬아본다면?'이라는 생각을 하게되어 출제하게 되었습니다.&lt;/li&gt;
&lt;li&gt;제가 적은 정해와 다르게 DP 부분을 O(min(F^3T, F^4)) 부분을 O(F^3logT)로도 푸신분들도 있었습니다. 또한, 전술간의 전환을 cost 1씩 증가하는 것으로 생각해서 2D cost에서 다익스트라로 푸는 별해도 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/30205&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 30205 전역 임무&lt;/a&gt; - S2
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;본선 B번 문제.&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbVVDq/btsC9ydrST6/BExXIne9VX7xsLPsnmS4U0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbVVDq/btsC9ydrST6/BExXIne9VX7xsLPsnmS4U0/img.jpg&quot; data-alt=&quot;이 게임을 모티브로 출제했습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbVVDq/btsC9ydrST6/BExXIne9VX7xsLPsnmS4U0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbVVDq%2FbtsC9ydrST6%2FBExXIne9VX7xsLPsnmS4U0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;686&quot; height=&quot;386&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;386&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이 게임을 모티브로 출제했습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;기억은 안 나지만 어느 스트리머가 &lt;a href=&quot;https://store.steampowered.com/app/2348100/YEAH_YOU_WANT_THOSE_GAMES_RIGHT_SO_HERE_YOU_GO_NOW_LETS_SEE_YOU_CLEAR_THEM/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;'Yeah! You Want &quot;Those Games,&quot; Right? So Here You Go! Now, Let's See You Clear Them!'&lt;/a&gt;에서 해당 게임을 너무 못해 속이 타서 최적해를 떠올리다가 문제로 내도 괜찮겠다는 생각이 들어 출제했습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;저랑 운영진들의 예상과는 다르게 대회중에 많은 분들이 고전했던 문제였습니다. 이 글을 보신분들 중에 혹여나 이 문제로 고통받으신 분들이 있다면 죄송합니다... (이 문제 때문에 배경을 못 받은 분들도 계셔서 마음이 아팠습니다 ㅠㅠ)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/30206&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 30206 차량 배치&lt;/a&gt; - G4
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;본선 C번 문제.&lt;/li&gt;
&lt;li&gt;이 문제는 LCA 관련 문제를 생각하다가 떠올린 문제였는데, BFS + 조합론은 많이 생소할 것 같아서 출제했습니다. 특히나 보라매컵에서 한 번도 조합론 문제가 나온적은 없어서 이렇게 스타트를 끊어보고도 싶었습니다.&lt;/li&gt;
&lt;li&gt;출제하는 것도 나머지 3문제 보다 비교적 훨씬 쉬었어서 편했던 문제였습니다. 그리고 문제 아이디어도 제 마음에 들었던 문제였는데, 꽤 좋은 평가를 받아서 매우 기뻤습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/30210&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 30210 BX 내기&lt;/a&gt; - P3
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;본선 G번 문제.&lt;/li&gt;
&lt;li&gt;XOR Trie를 좀 더 generalize하면 이렇게도 출제할 수 있지 않을까 생각해서 출제한 문제입니다. 이 문제를 통해서 보라매컵 참가자분들에게도 XOR Trie를 소개할 수 있으면 좋겠다라는 생각도 있었습니다.&lt;/li&gt;
&lt;li&gt;출제가 확정되고 나중에 들은건데, 실제 대회에서는 인터넷 사용이 금지되었다고 합니다. 그래서 Trie가 Segment Tree처럼 대회 참가자들에게는 잘 알려진 자료구조가 아니라 판단되어 Trie만 가능했으면(Trie 모르면 못 푸니깐) 출제할 수 없었는데, 다행이 다른 Maximal XOR 문제처럼 이 문제도 이분탐색을 활용해서 풀 수 있어 출제할 수 있었습니다.&lt;/li&gt;
&lt;li&gt;이 자리를 빌어 실제로 저런 게임을 한 적도 없고, &lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;s&gt;하더라도 바보게임만 4시간 동안 돌렸지&lt;/s&gt;&lt;/span&gt; 후임들에게 계산하라고 시킨적은 한 번도 없음을 밝힙니다. 부조리는 근절되어야 합니다 :)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴 글 읽어주셔서 감사합니다. 올해도 다들 즐거운 PS 생활하세요 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/기타</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/58</guid>
      <comments>https://jun9985.tistory.com/58#entry58comment</comments>
      <pubDate>Mon, 8 Jan 2024 03:59:29 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.07.</title>
      <link>https://jun9985.tistory.com/57</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 12869 뮤탈리스크 - G4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS + DP 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;범위가 매우 작으므로 {0,0,0} 부터 시작해서 {60,60,60} 상태까지 전부 BFS를 해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS를 하면 결국에는 DP 테이블이 채워진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 랜덤디펜스로 풀었으면 G3으로 올라가는 거였는데... 시간도 안 쟀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한동안 코타키나발루 여행가면 계속 B5만 올릴듯;;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/57</guid>
      <comments>https://jun9985.tistory.com/57#entry57comment</comments>
      <pubDate>Mon, 8 Jan 2024 01:43:16 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.06.</title>
      <link>https://jun9985.tistory.com/56</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 9654 나부 함대 데이터 - B5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스트릭용 Text 제출 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내일은 좀 열심히 해야지... (어차피 다음 주는 아마 이렇게 스트릭만 유지할듯...?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/56</guid>
      <comments>https://jun9985.tistory.com/56#entry56comment</comments>
      <pubDate>Sun, 7 Jan 2024 00:44:31 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.05.</title>
      <link>https://jun9985.tistory.com/55</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 5339 콜센터 - B5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설명은 귀여운 C3PO로 대체함.&lt;/p&gt;
&lt;pre id=&quot;sample-output-1&quot; class=&quot;gherkin&quot; style=&quot;background-color: #f7f7f9; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;     /~\
    ( oo|
    _\=/_
   /  _  \
  //|/.\|\\
 ||  \ /  ||
============
|          |
|          |
|          |&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[랜덤디펜스]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0. BOJ 23257 비트코인은 신이고 나는 무적이다 - G3 -&amp;gt; Fail.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배낭 문제인지 아니면 Bitmasking + DFS 인지가 계속 헷갈렸는데, 배낭 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;47분 정도 고민하다가 GG친 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내일 일어나서 다시 한 번 봐야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/55</guid>
      <comments>https://jun9985.tistory.com/55#entry55comment</comments>
      <pubDate>Sat, 6 Jan 2024 04:44:36 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.04.</title>
      <link>https://jun9985.tistory.com/54</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 3 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 4999 아! - B5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열 비교 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 길이끼리 비교하면 되는 문제였다. 스트릭 유지용으로 푼 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[업다운 랜덤디펜스] (다시 시작)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그는 기하학만 빼고 진행, 100명 이상 푼 문제를 1시간 내로 푸는 것을 목표로 하고 G5부터 시작.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 12025 장난꾸러기 영훈 - G5 (Solved - 08: 24)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비트마스킹 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1,2,6,7만 바뀌는데 위치가 제일 뒤에 있는 순서부터 바꿀지 말지를 결정하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 홀수면 항상 맨 뒤의 1,2,6,7은 6 아니면 7로 바뀌어야 하고, 4의 배수는 아니나 2의 배수면 맨 뒤에서 두 번째가 바뀌어야 하고 ... 이러한 규칙성 때문에 그냥 K를 2로 나눈 나머지를 보고 2로 계속 나눠서 구하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 총 시간복잡도는 O(|S| log K).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. BOJ 28283 해킹 - G4 (Solved - 09:39)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS + Sorting + Greedy 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;X+0.5초후에 보안 프로그램이 깔리면 X초까지는 해킹된다는 것이므로, 처음에 보안 프로그램이 깔리는 컴퓨터들을 거리가 0으로 둔 상태에서 BFS를 돌리면 각 컴퓨터가 몇 초까지 해킹되는지 파악이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 각 컴퓨터마다 a[i] * 해킹이 가능한 시간을 구하고 그 중에서 숫자가 제일 큰 X개를 골라서 더하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, BFS로도 탐색이 안 되는데 a[i]가 0보다 큰 노드가 있다면 -1를 출력하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 시간복잡도는 O(N+M+NlogN)이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 읽을 때 타이머가 안 누르고 했어서 읽는 시간 2분 정도 페널티를 두고 시작했다. (사실 읽는데도 2분은 안 걸리긴 했을 듯?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/54</guid>
      <comments>https://jun9985.tistory.com/54#entry54comment</comments>
      <pubDate>Fri, 5 Jan 2024 00:15:05 +0900</pubDate>
    </item>
    <item>
      <title>2024.01.03.</title>
      <link>https://jun9985.tistory.com/53</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;백준 2 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BOJ 14289&amp;nbsp; 본대 산책 3 - G1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할정복을 활용한 거듭제곱 + 그래프 이론 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인접행렬을 k번 거듭제곱하면 각 adj[i][j]마다 k번 이동했을 때에 i -&amp;gt; j로 가는 경우의 수임을 알면 쉽게 풀 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;증명도 생각해보면 어렵지 않게 가능해서 좋아하는 문제 유형이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. BOJ 2485 가로수 - S4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유클리드 호제법 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가로수 간의 거리를 동일하게 쪼갤 수 있는 거리 중에 최댓값을 찾고 싶으므로 결국에는 가로수 간의 거리들의 GCD를 찾으면 된다. 이를 유클리드 호제법이나 C++ 내장 함수 중 __gcd(a,b) 함수로 빠르게 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문게시판 기웃거리다가 찾은 담백한 실버 수학 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 일지는 여기서 끝.&lt;/p&gt;</description>
      <category>Algorithm &amp;amp; PS/PS 일지</category>
      <author>junhyung9985</author>
      <guid isPermaLink="true">https://jun9985.tistory.com/53</guid>
      <comments>https://jun9985.tistory.com/53#entry53comment</comments>
      <pubDate>Thu, 4 Jan 2024 05:18:46 +0900</pubDate>
    </item>
  </channel>
</rss>