<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Clockwise</title>
    <link>https://bnb2011.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 5 Aug 2026 03:57:40 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>IBory</managingEditor>
    <image>
      <title>Clockwise</title>
      <url>https://tistory1.daumcdn.net/tistory/4890314/attach/3c4e656d637a462a9449dc340b0fa2e3</url>
      <link>https://bnb2011.tistory.com</link>
    </image>
    <item>
      <title>[UCPC 2024] 팀원을 구합니다 (마감)</title>
      <link>https://bnb2011.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://2024.ucpc.me/&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;UCPC 2024&lt;/span&gt;&lt;/a&gt;에 같이 나갈 팀원을 구하고 있습니다. 아직 다른 팀원은 없고 저 혼자입니다...&lt;br&gt;개인적으로는 이번에 나가는 대회가 대학생 신분으로 나갈 수 있는 마지막 대회가 될 확률이 높아서, 특별상 수상권 (15등 언저리) 안에 드는 걸 목표로 하고 있습니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;아래는 간단한 소개입니다.&lt;br&gt;- 백준: &lt;a href=&quot;https://www.acmicpc.net/user/bnb2011&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;bnb2011&lt;/span&gt;&lt;/a&gt; (solved.ac R5, 4000 Solve)&lt;br&gt;- CF: &lt;span style=&quot;color: #F89009;&quot;&gt;IBory&lt;/span&gt; (2157, max 2279)&lt;br&gt;- AC: &lt;span style=&quot;color: #A6BC00;&quot;&gt;IBory&lt;/span&gt; (2047, max 2055)&lt;br&gt;- 2021 SCPC 4등상, 2023 5등상&lt;br&gt;- '21 MOBIS 알고리즘 경진대회 5등상, '23 학생부 장려상&lt;br&gt;&amp;nbsp;&lt;br&gt;관심 있으신 분은 오픈 카톡으로 연락 부탁드립니다 :D&lt;br&gt;&lt;br&gt;(2024.06.20 수정)&lt;br&gt;팀을 구해서 마감했습니다!&lt;/p&gt;</description>
      <category>etc.</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/13</guid>
      <comments>https://bnb2011.tistory.com/13#entry13comment</comments>
      <pubDate>Thu, 16 May 2024 01:14:43 +0900</pubDate>
    </item>
    <item>
      <title>Codeforces Round #914 (Div. 2)</title>
      <link>https://bnb2011.tistory.com/12</link>
      <description>&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Hello 2024 라운드를 대비하기 위해 버츄얼을 돌았다. &lt;a href=&quot;https://codeforces.com/profile/FD..LH..lloyJ&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;FD..LH..lloyJ&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;(김도훈이라고 읽는다고 한다..)와 &lt;a href=&quot;https://codeforces.com/profile/sharaelong&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff8c00;&quot;&gt;sharaelong&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;님이랑 같이 돌았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;51&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6BE6B/btsDbfLmXBJ/LBfKUXo7IkV0Eqk0CwhTQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6BE6B/btsDbfLmXBJ/LBfKUXo7IkV0Eqk0CwhTQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6BE6B/btsDbfLmXBJ/LBfKUXo7IkV0Eqk0CwhTQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6BE6B%2FbtsDbfLmXBJ%2FLBfKUXo7IkV0Eqk0CwhTQ0%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;1184&quot; height=&quot;51&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;51&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;특이사항으로는 E, F가 모두 난이도 있는 트리 문제였는데, 두 문제 다 예전에 풀어본 문제들 중 하나랑 비슷한 점이 있었는데도 불구하고 대회 시간 내에 해결하지 못했다. 다만 D와 E의 난이도 차이가 커서 그런지 퍼포먼스는 &lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;b&gt;2432&lt;/b&gt;&lt;/span&gt;가 나왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1905&quot;&gt;https://codeforces.com/contest/1905&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A. Forked! [00:09:46, -1]&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;*900&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;a href=&quot;https://codeforces.com/contest/1904/submission/240241771&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1904/submission/240241771&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;B. Collecting Game [00:13:50]&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;*1100&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;배열 $A$의 값이 커질수록 답은 단조적으로 증가한다. 따라서 배열 $A$를 정렬한 뒤, 투 포인터를 이용해 각 값에 대해 답을 전처리해 줄 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1904/submission/240242324&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1904/submission/240242324&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C. Array Game [00:21:13]&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;*1400&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;우선 연산을 세 번 이상 할 수 있다면 항상 답은 $0$이 됨을 관찰해야 한다. 같은 인덱스 쌍을 두 번 고르면 두 개의 같은 수가 나오고, 같은 수가 존재한다면 연산을 이용해 $0$을 만들 수 있기 때문이다.&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;이제 연산을 두 번 사용해 답을 최소로 만드는 방법을 알아보자. (한 번은 쉬우니까...) 우선 $O(N^2)$가지 모든 경우를 계산한다. 그러면 두 번째 연산은 $A_i$와 앞에서 만든 $O(N^2)$개 값 중 하나를 연산에 사용할 수 있다. 이분 탐색을 이용하면 각 $A_i$에 대해 가장 절댓값 차가 작은 후보 값을 구해줄 수 있으니, &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;$O(N^2logN)$에 문제를 해결 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1904/submission/240243266&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1904/submission/240243266&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D1, D2. Set to Max [00:37:00]&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;*1600, *1800&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;D2 풀이가 먼저 보여서 D1만 통과하는 풀이를 따로 고민해보진 않았다.&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;$B_i$가 작은 위치부터 하나씩 맞춰가는 방식을 사용한다. 어떤 $A_i$를 $B_i$로 만들 수 있다는 것은, 처음부터 $A_i = B_i$ 이거나 $A_i &amp;lt; B_i$ 이면서 $\max$ 쿼리를 이용해 $B_i$에 해당하는 값을 가져올 수 있음을 의미한다.&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;현재 위치 $p$에서 가장 가까우면서 $A$의 값이 $B_p$인 지점을 $pos$라고 하자. $pos$에서 값을 가져오기 위해선 $p$와 $pos$ 사이에 배열 $A$의 값 중 $B_i$보다 더 큰 값이 없어야 하고 ($\max$ 쿼리의 결과가 $B_i$가 되어야 하므로), 배열 $B$의 값 중 $B_i$보다 더 작은 값이 없어야 한다. (이미 조건을 만족한 정점들의 결과가 변하므로)&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;특정 위치에서 가장 가까운 다른 위치를 찾는 것과, 특정 구간에 조건을 만족하는 점이 존재하는지 판별하는 것은 모두 set을 잘 쓰면 $log$ 시간에 가능하다. 따라서 $O(NlogN)$에 문제를 해결할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1905/submission/239896694&quot;&gt;https://codeforces.com/contest/1905/submission/239896694&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;E. Tree Queries [Upsolved]&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;*2500&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/20640&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Towns and Roads&lt;/a&gt; 라는 문제와 비슷한 아이디어를 사용한다. 모든 정점과의 거리를 세그먼트 트리의 노드에 저장해 두면, Max Range Query를 날려서 가장 멀리 떨어진 정점과의 거리를 구할 수 있음을 이용한다. (이때 저장하는 위치는 오일러 투어의 방문 순서에 해당한다)&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;쿼리를 오프라인으로 처리한다. 루트 정점에서 시작해, 다른 모든 정점으로 DFS로 한 번씩 방문하면서 각 정점에 해당하는 쿼리의 답을 계산한다. 부모 정점에서 자식 정점으로 이동할 때는 자식 정점의 서브트리에 속하는 모든 정점의 거리는 $1$ 감소하고, 이외의 모든 정점의 거리는 $1$ 증가한다. ETT를 이용하면 이를 구간 업데이트로 처리할 수 있다.&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;쿼리를 처리할 때는 어떤 정점이 삭제되었을 때 도달하지 못하게 되는 정점 역시 구간을 이룸을 이용한다. 도달이 불가능한 구간에 -INF 만큼을 더해주는 방식을 이용하면, Range Max Query를 그대로 이용해 가장 멀리 떨어진 정점을 잘 찾을 수 있다. 조상 정점이 삭제되는 경우 처리가 조금 까다로울 수 있는데, 이때는 반대로 도달 가능한 구간에 INF만큼을 더해주는 것으로 유사하게 처리가 가능하다. 시간복잡도는 $O((N + Q + K)logN)$이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1904/submission/240294164&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1904/submission/240294164&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;F. Beautiful Tree [Upsolved]&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;*2800&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;두 수의 대소 관계를 그래프의 간선을 이용해 나타낸다. 구체적으로는 정점 $n$에 할당해야 하는 값을 $P_n$이라 했을 때, $P_i &amp;lt; P_j$가 되어야 한다면 $i \rightarrow j$ 와 같이 간선을 그어준다.&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;문제는 모든 간선을 그냥 그으면 $O(N^2)$개의 간선을 만들어야 하는데, 간선을 그어야 하는 영역이 &lt;b&gt;구간&lt;/b&gt;으로 나타남을 이용한다. 적당한 전처리를 해두면 모든 구간을 $O(log^2N)$개의 정점으로 나눌 수 있고, 이를 이용해 유효한 간선의 개수를 $O(Nlog^2N)$개로 줄일 수 있다. ($O(log^2N)$개인 이유는 HLD를 이용해 트리의 경로를 $O(logN)$개의 구간으로 나눈 뒤, 나눈 구간을 다시 $O(logN)$개의 정점으로 나누기 때문이다.)&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;이렇게 만든 그래프에서 위상 정렬이 가능한지를 판별하고, 가능하다면 방문한 순서대로 정점에 값을 할당해 주면 $O(Nlog^2N)$에 문제를 해결할 수 있다. 구현은 JOISC 2021/2022의 &lt;a href=&quot;https://www.acmicpc.net/problem/24942&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Jail&lt;/a&gt;과 비슷했던 것 같다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1904/submission/240332849&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1904/submission/240332849&lt;/a&gt;&lt;/p&gt;</description>
      <category>CodeForces</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/12</guid>
      <comments>https://bnb2011.tistory.com/12#entry12comment</comments>
      <pubDate>Sun, 7 Jan 2024 13:44:22 +0900</pubDate>
    </item>
    <item>
      <title>Codeforces Round #915 (Div. 2)</title>
      <link>https://bnb2011.tistory.com/11</link>
      <description>&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;지난번에 있었던 코포 라운드에서 뜻하지 않게 탑레를 갱신하게 되었다. 다운보트를 무려 4000개나 받은 역대급 셋이었지만 내가 많이 올랐으면 된 게 아닐까..?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1185&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lgtg8/btsCTCPwPqP/AhMV8kqsR5PLo91RqILkzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lgtg8/btsCTCPwPqP/AhMV8kqsR5PLo91RqILkzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lgtg8/btsCTCPwPqP/AhMV8kqsR5PLo91RqILkzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flgtg8%2FbtsCTCPwPqP%2FAhMV8kqsR5PLo91RqILkzk%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;1185&quot; height=&quot;53&quot; data-origin-width=&quot;1185&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;891&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/23kxk/btsCSA5rYka/NrMpVJdu8UOFLkv01CBQFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/23kxk/btsCSA5rYka/NrMpVJdu8UOFLkv01CBQFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/23kxk/btsCSA5rYka/NrMpVJdu8UOFLkv01CBQFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F23kxk%2FbtsCSA5rYka%2FNrMpVJdu8UOFLkv01CBQFk%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;896&quot; height=&quot;891&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;891&quot;/&gt;&lt;/span&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;a href=&quot;https://codeforces.com/profile/kongum&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #03a89e;&quot;&gt;kongum&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;과 &lt;b&gt;&lt;span style=&quot;color: #ff8c00;&quot;&gt;&lt;a style=&quot;color: #ff8c00;&quot; href=&quot;https://codeforces.com/profile/leo020630&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;leo020630&lt;/a&gt;&lt;/span&gt;&lt;/b&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;1166&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7LIoF/btsC2zDNfLP/xH27TuuLUCUCXORZ4rPIe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7LIoF/btsC2zDNfLP/xH27TuuLUCUCXORZ4rPIe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7LIoF/btsC2zDNfLP/xH27TuuLUCUCXORZ4rPIe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7LIoF%2FbtsC2zDNfLP%2FxH27TuuLUCUCXORZ4rPIe1%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;1166&quot; height=&quot;37&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 셋 퀄리티는 좋았고, 난이도 밸런스도 적당했다. 아쉬웠던 점은 1시간 정도 남기고 E, F를 둘다 못 풀었다는 점인데, 둘 다 그렇게 어려운 문제가 아니었어서 조금 아쉽게 느껴진다. 예상 퍼포먼스는 &lt;b&gt;&lt;span style=&quot;color: #ff8c00;&quot;&gt;2305&lt;/span&gt;&lt;/b&gt;가 나왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1905&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1905&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A. Constructive Problem [00:02:01]&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;*800&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;초기 배치하는 칸을 대각선으로 이어지게 잘 배치해주면 된다. 따라서 답은 $\max(N, M)$이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1905/submission/239892230&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1905/submission/239892230&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;B. Begginer's Zelda [00:06:01]&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;*1100&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;문제의 목표는 리프 노드의 개수를 $0$개로 만드는 것이다. 현재 리프 노드가 세 개가 아니라면, 항상 두 리프 노드를 합쳤을 때 만들어진 노드가 리프가 아니도록 만들 수 있다. 따라서 리프 노드의 개수를 두 개씩 감소시켜 가되, 개수가 세 개일 때만 예외적으로 처리를 해주면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 시뮬레이션 결과를 일반화하면, 주어진 트리의 리프 노드 개수를 $L$이라 했을 때 답은 $\lceil \frac{L}{2} \rceil$이 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1905/submission/239892645&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1905/submission/239892645&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C. Largest Subsequence [00:27:36, -2]&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;*1400&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제에서 주어진 연산을 반복적으로 적용한 결과는 결국 주어진 문자열에서 Largest Subsequence를 찾고 그 문자열을 뒤집는 것과 동일하다. 단, 연산을 계속 진행하다가 Largest Subsequence가 같은 문자로만 구성되어 있을 경우에는 연산을 적용해도 결과가 동일하므로 더 진행할 필요가 없다. 따라서 답은 (Largest Subsequence의 길이) - (Largest Subsequence를 구성하는 사전순으로 가장 큰 문자의 개수)가 된다. 스택 같은 걸 써서 Largest Subsequence를 $O(N)$에 구할 수 있으니, 전체 문제도 $O(N)$에 해결할 수 있다.&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;a href=&quot;https://codeforces.com/contest/1905/submission/239894998&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1905/submission/239894998&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D. Cyclic MEX [00:43:06]&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;*2000&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Prefix $\text{mex}$가 가지는 성질에 대한 관찰이 필요하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$1 \le k &amp;lt; N$일 때 구간 $[1, k]$에서의 $\text{mex}$는 $[k + 1, N]$ 구간의 최솟값과 같다.&lt;/li&gt;
&lt;li&gt;$k = N$일 때는 주어진 수열이 순열이므로 항상 $\text{mex}$가 $N + 1$이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p 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;이에 따라 Cyclic Shift를 한 번 하게 되면 $\text{mex}$에는 다음과 같은 변화가 일어난다는 것을 알 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$k = 1$에 해당하는 $\text{mex}$가 사라진다.&lt;/li&gt;
&lt;li&gt;현재 $\text{mex}$가&amp;nbsp;$P_1$보다 큰 값들은 모두 $P_1$로 변한다.&lt;/li&gt;
&lt;li&gt;$k = N$에 해당하는 $\text{mex}$가 생긴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p 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;따라서 매번 옮길 때마다 값의 변화를 직접 추적해줄 수 있다. map에 ($\text{mex}$ 값, 원소 개수)를 저장한 뒤, Cyclic Shift를 할 때마다 이분 탐색으로 값들을 옮겨주면 된다. 이렇게 값들을 묶어서 관리하게 되면, 값들을 옮기는 횟수의 총합은 $O(N)$에 바운드되기 때문에 $O(NlogN)$에 문제를 해결할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;$\text{mex}$가 단조적이라는 점을 이용하면 덱을 사용해서 $O(N)$에 문제를 해결할 수도 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1905/submission/239896694&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1905/submission/239896694&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;E. One-X [Upsolved]&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;*2400&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;$dp_n$: $n$개의 리프 노드가 있고, 루트의 번호가 $1$일 때의 답이라고 하자.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;리프 노드가 $n$개인 트리는 리프 노드가 $\lceil \frac{n}{2} \rceil$, $\lfloor \frac{n}{2} \rfloor$개인 두 개의 서브 트리를 자식으로 갖는다. 그래서 $dp_{\lceil \frac{n}{2} \rceil}$과 $dp_{\lfloor \frac{n}{2} \rfloor}$를 잘 조합하면 $dp_n$의 값도 구할 수 있을 것 같다.&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$이 아니므로, 값을 합칠 때 차이를 잘 보정해줘야 한다. 차이가 얼마나 생기는지는 트리를 좀 끄적이다보면 알 수 있는데, 다음과 같은 값들을 정의하자. 모두 루트의 번호는 $1$이라고 가정한 값들이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$L_{n, k}$: $n$개의 리프가 있는 트리에서, $k$번 정점을 루트로 하는 서브트리에 포함된 리프의 개수&lt;/li&gt;
&lt;li&gt;$C_n$: $n$개의 리프가 있는 트리에서, 루트를 LCA로 가지는 리프 집합의 개수&lt;/li&gt;
&lt;li&gt;$T_n$: $n$개의 리프가 있는 트리에 포함된 정점 번호의 집합&lt;/li&gt;
&lt;li&gt;$d_k$: $k$번 정점과 루트와의 거리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 $up_n: \sum_{k \in T_n} {2^{d_k}C_{L_{n, k}}}$라 하자. 그러면 루트가 $a$일 때 모든 LCA의 합은 $dp_n + (a - 1) \times up_n$이 됨을 알 수 있다. 이제 다음 식들을 잘 조합하면 구하고자 하는 $dp_n$의 값을 구할 수 있다. 실제로 구해야 하는 $dp$ 값의 개수는 $log$개 이므로, 메모이제이션을 잘해주면 시간복잡도는 $O(log^2N)$이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$C_n = 2^n - 1 - (2^{ \lceil \frac{n}{2} \rceil } - 1) - (2^{ \lfloor \frac{n}{2} \rfloor } - 1)$&lt;/li&gt;
&lt;li&gt;$up_n = 2 \times up_{ \lceil \frac{n}{2} \rceil } + 2 \times up_{ \lfloor \frac{n}{2} \rfloor } + C_n$&lt;/li&gt;
&lt;li&gt;$dp_n = dp_{ \lceil \frac{n}{2} \rceil } + up_{ \lceil \frac{n}{2} \rceil } + dp_{ \lfloor \frac{n}{2} \rfloor } + 2 \times up_{ \lfloor \frac{n}{2} \rfloor } + C_n$&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1905/submission/240070755&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1905/submission/240070755&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;F. Field Should Not Be Empty [Upsolved]&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;*2600&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;처음에 good인 인덱스의 수가 $N$개라면 항상 답은 $N - 2$이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이외의 경우에는 swap을 해서 답을 증가하도록 만들 수 있다. 따라서 swap을 할 수 있는 $O(N^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;swap에 의해 간접적으로 good이 되는 경우와 직접적으로 good이 되는 경우로 나눠서 생각해 보자. 직접적이라는 것은 swap 한 값이 good이 되는 것을 말하고, 간접적이라는 것은 swap 하지 않은 값이 good이 되는 것을 말한다.&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;어떤 인덱스 $k$가 간접적으로 good이 되려면 적어도 다음 세 가지 조건을 만족하고 있어야 한다. swap은 Point Update 이므로, 양쪽에서 최대 하나씩의 값만 변화시킬 수 있기 때문이다.&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;$P_k = k$&lt;/li&gt;
&lt;li&gt;$[1, k)$ 구간에서 $k$보다 큰 수가 최대 한 개&lt;/li&gt;
&lt;li&gt;$(k, N]$ 구간에서 $k$보다 작은 수가 최대 한 개&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2, 3번 조건에 해당하는 수가 모두 한 개라면, swap을 했을 때 답이 증가하는 경우가 유일하다. 따라서 이 경우에 해당하는 swap은 $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;직접적으로 good인 인덱스를 만들기 위해서는 또는 $P_i$와 $i$를 swap해야 한다. 이 경우에 해당하는 swap도 $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;이제 어떤 swap이 유효한지 알았으니, 가능한 경우를 모두 해보고 그 중 최대가 되는 경우를 찾으면 된다. 에디토리얼에서는 세그를 썼는데, set이랑 map 떡칠을 해도 문제를 해결할 수 있다. 내 풀이는 이분 탐색을 사용하고 있어서 $O(NlogN)$이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1905/submission/240085316&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1905/submission/240085316&lt;/a&gt;&lt;/p&gt;</description>
      <category>CodeForces</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/11</guid>
      <comments>https://bnb2011.tistory.com/11#entry11comment</comments>
      <pubDate>Thu, 4 Jan 2024 05:46:29 +0900</pubDate>
    </item>
    <item>
      <title>Codeforces Round #905 (Div. 1)</title>
      <link>https://bnb2011.tistory.com/10</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;레드가 가고 싶다던 &lt;a href=&quot;https://codeforces.com/profile/Jeuti&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Jeuti&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;와 버츄얼을 돌았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;89&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M7V5n/btsCMput6k7/CkNa6j3twGGqSsyBkgPva0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M7V5n/btsCMput6k7/CkNa6j3twGGqSsyBkgPva0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M7V5n/btsCMput6k7/CkNa6j3twGGqSsyBkgPva0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM7V5n%2FbtsCMput6k7%2FCkNa6j3twGGqSsyBkgPva0%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;1179&quot; height=&quot;89&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;89&quot;/&gt;&lt;/span&gt;&lt;/figure&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;a href=&quot;https://codeforces.com/contest/1887&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1887&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A1. Dances (Easy version) [00:07:42] &lt;/b&gt;*1400&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Easy version 에서는 한 번만 비교해 주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최적의 결과는 $A$와 $B$ 배열을 각각 정렬한 뒤, $A$의 Prefix와 $B$의 Suffix를 순서대로 매칭시켜 봄으로써 얻을 수 있다. 이제 답에 대한 이분 탐색을 하면 $O(NlogN)$에 풀 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1887/submission/239066721&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1887/submission/239066721&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A2. Dances (Hard version) [00:50:19, -1]&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;*1900&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Hard version 에서는 $M$번이나 비교해야 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;배열에 더 큰 값이 있을수록 매칭을 시키는 것이 어려워진다. 따라서 $A_1$의 값에 따라 답이 단조적으로 감소함을 알 수 있다. 물론 $M$이 $10^9$이기 때문에, &lt;b&gt;답이 같은 구간&lt;/b&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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;답이 변할 수 있는 구간 후보는 $O(N)$개 존재한다. 왜냐면 $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;답을 빠르게 계산하기 위해 다음과 같은 새로운 값을 구한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$P_i$: $A_i$를 $B$에 매칭하기 위해 옮겨야 하는 최소 칸 수&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;항상 같은 위치에 있거나 더 오른쪽에 있는 수와 매칭시켜야 하므로 $P_i$는 $0$ 이상이고, $A_{i-1}$의 매칭 위치보다 더 오른쪽에 있어야 하기 때문에 $1 &amp;lt; i$일 때 $P_{i - 1} &amp;lt; P_i$를 만족해야 한다. 이를 만족하는 $P_i$의 값들은 $A_1 = 1$이라고 했을 때 이분 탐색을 이용해 총 $O(NlogN)$에 전처리를 해줄 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;$P$를 이용해 답을 계산하는 과정은 다음과 같다. 답이 $k$ 이상이라는 것은 $1 ~ k$ 사이의 모든 값들이 최대 $N - k$칸을 옮겨서 안에 매칭을 할 수 있다는 말과 같다. 따라서 $P$의 Prefix Max 값을 잘 찾을 수 있다면 답을 구할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 모든 구간 경계의 후보를 오름차순으로 정렬한 뒤, 각 후보에 대해 하나씩 답을 계산한다. 값이 증가할 때마다 오른쪽으로 한 칸씩 이동하니, 위치가 갱신될 때마다 $P$의 값도 같이 경신해 줄 수 있다. 이러면 전체 문제를 $O(NlogN)$에 해결가능하다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1887/submission/239067206&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1887/submission/239067206&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 답은 최대 $1$ 변한다. 애초에 정렬했을 때 원래 위치에서 최대 한 칸까지 밖에 못 움직이기 때문이다. 그래서 답이 변하는 지점을 이분 탐색으로 찾아줘도 무방하다. 이러면 $O(NlogNlogM)$에 문제를 해결할 수 있다. 역시 머리가 나쁘면 몸이 고생한다는 것을 느꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1887/submission/239074208&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1887/submission/239074208&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;B. Time Travel [01:14:30]&lt;/b&gt; *1900&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;&lt;a href=&quot;https://codeforces.com/contest/1887/submission/239067399&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1887/submission/239067399&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C. Minimum Array [Upsolved]&lt;/b&gt; *2400&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;$i$번 쿼리까지 완료한 시점과 $j, (i &amp;lt; j)$번 쿼리까지 완료한 시점 중, 어떤 시점이 사전순으로 더 최소인지 비교하기 위해서는 $[i + 1, j]$번 쿼리 사이의 변화값을 알고 있으면 된다. 가장 처음으로 등장하는 $0$이 아닌 값이 음수면 $j$가 사전순으로 더 작고, 양수면 $i$가 사전순으로 더 크다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 사실을 이용하면 답을 그리디하게 구할 수 있다. 기본적으로는 쿼리를 그대로 시뮬레이션하면서, 이분 탐색을 이용해 값이 $0$이 아닌 첫 지점을 찾는다. 그리고 새로운 사전순 최소가 되는 지점을 찾을 때마다 세그먼트 트리를 다시 리셋해 주면 된다. $O(N + QlogN)$에 문제를 해결할 수 있다.&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;레이지 세그먼트 트리를 쓰지 않고도 문제를 해결할 수 있다. $D_i = A_{i + 1} - A_i$로 정의한 차수열을 생각해보자. 원본 배열 $A$와 차수열 $D$의 사전순 정렬 순서는 동일하기 때문에, $D$에서 문제를 해결해 줘도 동일하게 답을 구할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 문제를 변환했을 때의 좋은 점은 Range Update를 Point Update로 바꿀 수 있기 때문에 set과 같은 BBST를 이용해서 시뮬레이션을 할 수 있다는 것이다. 시간복잡도는 세그먼트 트리를 이용했을 때와 동일하고, 구현이 훨씬 쉽다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1887/submission/238911008&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1887/submission/238911008&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D. Split [Upsolved]&lt;/b&gt; *2700&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;조건을 만족하는 Maximal한 구간들을 다 구해두고, 쿼리로 들어오는 구간이 미리 구해둔 구간 중 하나에 속하는지를 판별하는 식으로 문제를 해결한다. 이런 Maximal한 구간들을 구할 수 있다면, 쿼리를 처리하는 건 세그먼트 트리 들고 스위핑을 함으로써 구할 수 있다.&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;Maximal한 구간을 찾는 방법을 생각해 보자. 다음 값들을 알고 있을 때 $A_i$가 병목이 되면서 최대가 되는 구간의 길이를 구할 수 있다. 병목이 된다는 것은 &lt;i&gt;good&lt;/i&gt; 인 배열의 왼쪽 부분의 최댓값이 $A_i$가 됨을 의미한다고 하자.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;$L_i$ = $i$보다 작으면서, $A_i$보다 큰 값 중 가장 오른쪽에 있는 값&lt;/li&gt;
&lt;li&gt;$M_i$ = $i$보다 크면서, $A_i$보다 큰 값 중 가장 왼쪽에 있는 값&lt;/li&gt;
&lt;li&gt;$R_i$ = $M_i$보다 크면서, $A_i$보다 작은 값 중 가장 왼쪽에 있는 값&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 값들은 모두 set을 들고 스위핑을 하면 어렵지 않게 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 $A_i$가 병목이 되는 구간 중 Maximal한 구간은 $[L_i + 1, R_i - 1]$가 된다. 단, 구간은 반드시 $M_i - 1$과 $M_i$를 지나야 한다. 즉, 구간의 왼쪽 $l$은 $L_i &amp;lt; l &amp;lt; M_i$을, 오른쪽 $r$은 $M_i \le r &amp;lt; R_i$를 만족해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$l$이 위치할 수 있는 구간을 2차원 좌표평면의 $x$축으로, $r$이 위치할 수 있는 구간을 2차원 좌표평면의 $y$축으로 생각하면 직사각형 영역이 생긴다. 그러면 쿼리로 들어온 점이 직사각형 안에 위치하는가? 를 묻는 문제로 변환되고, 위에서 언급한 것과 같이 세그먼트 트리와 스위핑을 이용해 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1887/submission/239019330&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1887/submission/239019330&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;E. Good Colorings [Upsolved]&lt;/b&gt; *3100&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;색칠된 칸을 행과 열을 잇는 간선으로 생각하자. 이렇게 만든 그래프는 $2N$개의 정점과 $2N$개의 간선을 가진 이분 그래프가 된다. 그리고 문제에서 찾고자 하는 네 개의 색칠된 칸은 간선의 색이 모두 다르면서, 길이가 $4$인 사이클을 찾는 것이 된다.&lt;/span&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;우선 항상 조건을 만족하는 길이 $4$의 사이클을 만들 수 있음을 보인다. 직사각형 한 칸을 색칠하게 되면 사이클이 사이클 하나가 두 개로 나뉘게 된다. 이때, 원본 사이클을 구성하는 간선의 색깔은 모두 다르기 때문에, 인터랙터가 어떤 색깔로 새로 들어온 간선을 색칠하든 간에 원래 사이클보다 길이가 더 작으면서, 모든 간선의 색깔이 다른 사이클을 구성하는 것이 가능하다. 이렇게 문제를 축소시켜 나가다 보면 언젠가는 사이클의 길이가 $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;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;사이클을 나눌 때, 항상 사이클의 크기가 절반이 되도록 나누면 길이가 $log$ 스케일로 감소하기 때문에, 열 번의 쿼리 안에 조건을 만족하는 직사각형을 무조건 만들 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1887/submission/239042886&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1887/submission/239042886&lt;/a&gt;&lt;/p&gt;</description>
      <category>CodeForces</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/10</guid>
      <comments>https://bnb2011.tistory.com/10#entry10comment</comments>
      <pubDate>Sun, 31 Dec 2023 05:15:02 +0900</pubDate>
    </item>
    <item>
      <title>[ABC254 Ex] Multiply or Divide by 2</title>
      <link>https://bnb2011.tistory.com/9</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc254/tasks/abc254_h&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://atcoder.jp/contests/abc254/tasks/abc254_h&lt;/a&gt;&lt;br /&gt;kenkoooo 레이팅:&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;2499&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;체감 난이도:&lt;b&gt;&lt;span style=&quot;color: #8cb3be;&quot;&gt; P1&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Tag: Greedy, Bitmask&lt;/p&gt;
&lt;hr data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;$N$개의 수로 이루어진 두 multiset $A, B$가 주어진다. 다음 연산을 최소 횟수로 사용해서 $A$를 $B$와 같게 만들 수 있는지 구해야 하는 문제이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$A$에 있는 원소 $n$을 고른다. 그 원소를 지우고, $A$에 $2n$을 추가한다.&lt;/li&gt;
&lt;li&gt;$A$에 있는 원소 $n$을 고른다. 그 원소를 지우고, $A$에 $\lfloor \frac{n}{2} \rfloor$를 추가한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;본 대회 때는 풀지 못했던 문제이다. 접근의 큰 틀은 맞았으나, 세부적인 구현이 많이 꼬여 있었다. 다시 풀어보는데도 디버깅에 한 세월 쓴 거 봐서는 아마 시간이 좀 더 있었어도 못 풀었지 싶다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;주어지는 수들을 $2^a \times b$ 형태로 나타내어 보자. 여기서 $a$는 가능한 최댓값이다. $b$가 같은 수들끼리는 무조건 주어진 연산을 적용해서 상호 변환이 가능하다. 사용해야 하는 연산 횟수는 당연하게도 $a$의 차이이다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;$b$가 같은 수들끼리 변환을 하고자 할 때는, 가장 큰 수끼리 변환시켜주는 것이 최적이다. 따라서 각 $b$별로 우선순위 큐 같은 걸 사용해서 원소들을 관리하면 어렵지 않게 매칭을 시켜줄 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;나눗셈 연산을 한 번 사용하면 $a$가 $1$ 감소하고, $a$가 $0$인 경우에는 $b$가 절반으로 감소한다. $b$가 절반으로 감소하면 다시 새롭게 매칭이 일어날 수 있는 여지가 생기므로, $A$의 모든 원소가 $B$의 원소와 매칭될 때까지 이를 반복하면 된다. 주의할 점은 $b$는 감소하는 방향으로만 이동하기 때문에, Optimal한 성질을 만족하기 위해서는 $b$가 큰 것부터 매칭을 진행해야 한다. 시간복잡도는 $O(NlogNlogA)$ 이다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc254/submissions/47753733&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://atcoder.jp/contests/abc254/submissions/47753733&lt;/a&gt;&lt;/p&gt;</description>
      <category>AtCoder</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/9</guid>
      <comments>https://bnb2011.tistory.com/9#entry9comment</comments>
      <pubDate>Sun, 19 Nov 2023 19:45:14 +0900</pubDate>
    </item>
    <item>
      <title>[ABC221 H] Count Multiset</title>
      <link>https://bnb2011.tistory.com/8</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc221/tasks/abc221_h&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;https://atcoder.jp/contests/abc221/tasks/abc221_h&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;kenkoooo 레이팅:&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;2793&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;체감 난이도: &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;D5&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;Tag: DP, Combinatorics&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;두 수 $N, M$이 주어진다. $1$ 이상 $N$ 이하의 모든 정수 $k$에 대해, 아래 조건을 만족하는 &lt;b&gt;집합의 수&lt;/b&gt;를 $998\ 244\ 353$로 나눈 나머지를 구해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;집합에 있는 원소의 수는 $k$이다.&lt;/li&gt;
&lt;li&gt;모든 원소의 합은 $N$이다.&lt;/li&gt;
&lt;li&gt;같은 원소는 최대 $M$개까지 포함할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;집합은 순서를 구분하지 않기 때문에 막 세는 것이 조금 까다롭다. 핵심은 구하고자 하는 것을 잘 변형해서 세기 쉬운 형태로 잘 바꿔주는 것이다. 풀이에서는 순서를 구분해서 세도 되는 형태로 조건을 잘 변형한다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;$A$는 항상 오름차순으로 정렬되어 있다고 가정한다. 그리고 인접한 $A$의 차이가 합에 기여하는 정도를 대신 센다고 하자. 이러면 값의 순서에 따라 합에 기여하는 정도가 달라지므로, 순서라는 조건을 값으로 치환해서 생각할 수 있다.&lt;br /&gt;$A_0 = 0$이라고 생각하고, $B_i = A_i - A_{i - 1}$라고 하자. 그러면 구하고자 하는 건 아래 조건을 만족하는 $B$의 배열이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$B$에서 연속된 $0$의 개수는 최대 $M-1$개 이다. (같은 수가 $M$개 이상 등장할 수 없으므로)&lt;/li&gt;
&lt;li&gt;$B_1$은 양수이다. ($A_i$가 양수여야 하므로)&lt;/li&gt;
&lt;li&gt;$\sum_{i=1}^{k} {B_i \times \left( k - 1 + i \right) } = N$&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;모든 $k$에 대해 답을 구해야 하는 입장에서 세 번째 조건이 처리하기 까다롭다. 대신 여기서 인덱스를 뒤집어서 수를 센다고 하자. 그러면 두 번째 조건은 $B_k$가 양수여야 한다는 조건으로, 세 번째 조건의 식은 $ \sum_{i=1}^{k} {B_i \times i } = N$ 와 같이 변하게 된다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이제 아래와 같이 dp 상태를 정의해서 문제를 해결할 수 있다.&lt;br /&gt;$dp[n][s]$: $B$의 $n$번째 값까지 채웠고, 채운 원소의 합이 $s$가 되는 경우의 수&lt;br /&gt;세 번째 조건에 따라 $n$번째로 원소를 넣을 때는 $n, 2n, \cdots$ 에 해당하는 원소만 넣을 수 있다. 또, 조건을 편하게 다루기 위해 항상 양수인 값만 넣는다고 하자. $B$에 $0$이 들어가는 경우는 따로 처리해 줄 것이다. 이를 이용해 점화식을 세워보면 아래와 같다.&lt;br /&gt;$$dp[n][s] = \sum_{k = 1}^{ \lfloor \frac{s}{n} \rfloor } \sum_{t = 1}^{t \le \min(t, M -1)} dp[n-t][s-kn]$$&lt;br /&gt;시그마가 두 개 있어서 대충 생각하면 $O(N^3M)$ 같지만, 잘 생각해 보면 누적합으로 잘 처리할 수 있는 형태이다. 따라서 각 상태 계산을 $O(1)$에 할 수 있고, 전체 문제를 $O(N^2)$에 해결할 수 있다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc221/submissions/47596249&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;https://atcoder.jp/contests/abc221/submissions/47596249&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>AtCoder</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/8</guid>
      <comments>https://bnb2011.tistory.com/8#entry8comment</comments>
      <pubDate>Thu, 16 Nov 2023 18:01:57 +0900</pubDate>
    </item>
    <item>
      <title>[ABC241 Ex] Card Deck Score</title>
      <link>https://bnb2011.tistory.com/7</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc259/tasks/abc259_h&quot;&gt;https://atcoder.jp/contests/abc259/tasks/abc259_h&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kenkoooo 레이팅:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;2881&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체감 난이도:&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt; D3&lt;/span&gt;&lt;/b&gt; (근데 이 정도 난이도의 수학 문제는 풀어본 적이 없어서 잘 모르겠다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Tag: Math, Bitmask&lt;/span&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$N$ 종류의 카드가 있다. $i$번 종류의 카드는 $A_i$가 쓰여 있고, 총 $B_i$장이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$M$개의 카드를 고른 뒤, 그 카드에 있는 수를 모두 곱한 값을 $S$라고 하자. 카드를 고르는 &lt;b&gt;모든 경우에서의 $S$ 합&lt;/b&gt;을 $998\ 244\ 353$으로 나눈 나머지를 출력하는 문제이다. $N$이 $16$ 정도로 작다는 점을 유념하자.&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;수 범위가 무지하게 큰데, 겁먹지 말고 가능한 모든 경우의 수를 다항식으로 표현하는 것으로 시작한다. 구하고자 하는 답은 아래 다항식 $f(x)$의 $M$차 항의 계수이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ f(x) = \prod_{i=1}^{N}{ \sum_{j=0}^{B_i} {{A_ix}^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;$$ f(x) = \prod_{i=1}^{N}{ \frac{1 - {A_ix}^{B_i + 1}} {1 - A_ix} } $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 분모에 해당하는 다항식을 아래와 같이 여러 부분분수의 합으로 분해한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \prod_{i=1}^{N}{\frac{1}{1 - A_ix}} = \sum_{i=1}^{N} {\frac{c_i}{1-A_ix}} $$&lt;/p&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_i$를 찾는다. 일단 양변에 $\prod_{i=1}^{N}{1 - A_ix}$ 를 곱해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$1 = \sum_{i=1}^{N} c_i{\prod_{j=1 \\ j \neq i}^{N}{ (1 - A_jx)} } $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 모든 $c_i$는 주어진 조건에 따라 $\bmod$ 범위 내에서 유일하게 존재한다. 존재성에 대한 엄밀한 증명은 잘 이해하지 못했으나, 대충 $N-1$차 다항식이 $x$값이 다른 $N$개의 서로 다른 점을 지난다는 사실에서 유도되는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운이 좋게도 나머지 항들을 잘 소거해서 $c_i$를 쉽게 구할 수 있다. 주어진 다항식의 $x$에 $A_i ^ {-1}$을 대입하면, 아래와 같이 식이 정리되고, $c_i$를 모듈러 역원을 이용해 구할 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ 1 \equiv c_i{\prod_{j=1 \\ j \neq i}^{N}{ (1 - A_jA_i^{-1})} } \bmod 998\ 244\ 353$$&lt;/p&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)$의 $M$차항의 계수를 계산한다. $f(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;$$ f(x) = \sum_{i=1}^{N} {c_i \left[ ( \sum_{j=0}^{B_i} {{A_ix}^j} ) ( \prod_{j=1 \\ j \neq i}^{N}{ (1 - {A_ix}^{B_i + 1} )} ) \right] } $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ \prod_{j=1 \\ j \neq i}^{N}{ (1 - {A_ix}^{B_i + 1})} $ 에 해당하는 다항식의 항 개수가 $O(2^N)$개라는 점을 이용해서 답을 구할 수 있다. 이 부분의 항의 계수가 결정이 되면, 자동적으로 $ \sum_{j=0}^{B_i} {{A_ix}^j} $에 해당하는 부분의 항 계수도 결정이 된다. 따라서 앞 다항식의 모든 항에 대해, 계수를 잘 계산하면 전체 문제를 $O(N2^N logM)$ 시간에 해결할 수 있다.&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://atcoder.jp/contests/abc241/submissions/47561254&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://atcoder.jp/contests/abc241/submissions/47561254&lt;/a&gt;&lt;/p&gt;</description>
      <category>AtCoder</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/7</guid>
      <comments>https://bnb2011.tistory.com/7#entry7comment</comments>
      <pubDate>Tue, 14 Nov 2023 04:29:19 +0900</pubDate>
    </item>
    <item>
      <title>[ABC259 Ex] Yet Another Path Counting</title>
      <link>https://bnb2011.tistory.com/6</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc259/tasks/abc259_h&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://atcoder.jp/contests/abc259/tasks/abc259_h&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kenkoooo 레이팅:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;2406&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체감 난이도: &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;P1&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tag: DP, Sqrt Decomposition&lt;/p&gt;
&lt;hr data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$N \times N$ 크기의 격자 위에 수 $A_{i, j}$가 쓰여있다. 어떤 칸에서 인접한 오른쪽 칸이나 아래쪽 칸으로 이동할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 경로 중, 경로의 시작점과 끝점에 있는 수가 &lt;b&gt;같은&lt;/b&gt; 경로의 수를 구해야 하는 문제이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 수마다 독립적으로 문제를 해결하려고 시도해보자. 각 수의 등장 횟수를 $S_i$라고 표기한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(i) $S_i$가 작으면, $O(S_i ^ 2)$ DP를 이용해 문제를 해결할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ii) $S_i$가 크면, $O(N^2)$ 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;두 방법을 적용하는 기준점을 $k$라 하자. (ii)에 해당하는 경우는 $N^2 / k$ 가지이다. 따라서 $O(k^3 + N^4 / k)$ 에 문제를 해결할 수 있고, 조화평균에 따라 $k = N$으로 두는 경우가 최적이다. 따라서 시간복잡도는 $O(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;&lt;a href=&quot;https://atcoder.jp/contests/abc259/submissions/47530510&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://atcoder.jp/contests/abc259/submissions/47530510&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AtCoder</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/6</guid>
      <comments>https://bnb2011.tistory.com/6#entry6comment</comments>
      <pubDate>Sun, 12 Nov 2023 20:44:58 +0900</pubDate>
    </item>
    <item>
      <title>[ABC267 Ex] Odd Sum</title>
      <link>https://bnb2011.tistory.com/5</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;비정기적으로 ABC의 Ex 난이도에 해당하는 문제를 하나씩 풀고 포스팅해 볼 것이다. 고난이도 문제에서 교육적인 컨셉이나 개념을 얻어가서 공부 좀 해보자는데 의의를 두려고 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc267/tasks/abc267_h&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://atcoder.jp/contests/abc267/tasks/abc267_h&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kenkoooo 레이팅: &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;2422&lt;/span&gt;&lt;/b&gt; (오렌지지만, Ex 중에서는 가장 쉬운 편에 속하는 문제이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체감 난이도: &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;D5&lt;/b&gt;&lt;/span&gt; ~ &lt;b&gt;&lt;/b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;D4&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tag: FFT, Divide and Conquer&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$N$개의 원소로 이루어진 수열 $A$가 주어진다. 이 수열에서 &lt;b&gt;홀수&lt;/b&gt; 개의 원소를 골라, 그 합이 $M$이 되게 하는 경우의 수를 구하는 문제이다. $N$이 $100\ 000$으로 작지 않지만, $A$가 $10$밖에 되지 않는다는 점이 특이하다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다항식을 이용해서 문제를 해결한다. $k$차 항의 계수를 합이 $k$가 되도록 원소를 뽑는 경우의 수라고 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 원소 $a$를 뽑는 것은 다항식에 $x^a$를 곱하는 것과 같고, 뽑지 않는 것은 다항식에 $1$을 곱하는 것과 같다. 따라서 $A$에서 원소를 선택해서 만들 수 있는 모든 합을 $\prod_{i=1}^N (x^{A_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;홀수 개의 원소를 사용해야 한다는 조건을 식에 녹여보자. 내가 푼 방식을 먼저 설명하고, 그다음 정해의 논리를 설명한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원소 $k$가 $A$에서 등장하는 횟수를 $S_k$라 하자. 그러면 $k$만을 골라서 만들 수 있는 합은 $(x^k + 1)^{S_k}$와 같이 나타낼 수 있다. 여기서 $k$를 짝수 개 사용하는 경우의 수는 다항식의 $x^0$, $x^{2k}$, $\cdots$ 계수에 해당하고 홀수 개 사용하는 경우의 수는 다항식의 $x^k$, $x^{3k}$, $\cdots$ 계수에 해당한다. 따라서 특정 원소를 짝수 개 사용하는 경우의 수와 홀수 개 사용하는 경우의 수를 분리해 줄 수 있다.&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;이제 어떤 원소를 짝수 개 사용하고, 홀수 개 사용할 것인지를 정해준다. 짝수의 사용은 합의 Parity를 변화시키지 않으므로, $M$의 Parity와 사용한 홀수 원소 개수의 Parity는 동일하다. 따라서 오직 짝수 원소에 대해서만 그 수를 몇 개 사용할지를 정해주면 된다. 제한에서 짝수의 개수는 $5$개이므로, 홀짝을 정해주는 경우의 수는 $2^5 / 2 = 16$ 가지이다. 각 수마다 홀수 사용하는 경우랑 짝수 사용하는 경우를 각각 구한 뒤, FFT를 이용해 신나게 곱해주면 $O(2^4MlogM)$ 에 문제를 해결할 수 있다.&lt;/p&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://atcoder.jp/contests/abc267/submissions/47423326&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://atcoder.jp/contests/abc267/submissions/47423326&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정해는 Parity가 다른 두 값을 합치면 홀수가 되고, Parity가 같은 두 값을 합치면 짝수가 된다는 점을 이용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할 정복을 한다. 배열 $A$를 절반으로 가르고, 각 절반마다 홀수 개 사용하는 경우의 수랑 짝수 개 사용하는 경우의 수를 각각 계산한 뒤 FFT를 이용해 합친다. 모든 원소는 $O(logN)$번 합쳐지기 때문에 시간복잡도는 $O(MlogMlogN)$ 이다.&lt;/p&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://atcoder.jp/contests/abc267/submissions/47514410&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://atcoder.jp/contests/abc267/submissions/47514410&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AtCoder</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/5</guid>
      <comments>https://bnb2011.tistory.com/5#entry5comment</comments>
      <pubDate>Sun, 12 Nov 2023 03:41:11 +0900</pubDate>
    </item>
    <item>
      <title>Educational Codeforces Round 157</title>
      <link>https://bnb2011.tistory.com/4</link>
      <description>&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1737&quot;&gt;https://codeforces.com/contest/1737&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1197&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/co2m49/btszHsQbABn/CW3m57oSGdxqiIkOY1AZ11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/co2m49/btszHsQbABn/CW3m57oSGdxqiIkOY1AZ11/img.png&quot; data-alt=&quot;시스텟 돌기 전 스탠딩&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/co2m49/btszHsQbABn/CW3m57oSGdxqiIkOY1AZ11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fco2m49%2FbtszHsQbABn%2FCW3m57oSGdxqiIkOY1AZ11%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;1197&quot; height=&quot;138&quot; data-origin-width=&quot;1197&quot; data-origin-height=&quot;138&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;hr data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A. Treasure Chest [00:03:35]&lt;/b&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;상자가 열쇠보다 왼쪽에 있다면 가능한 상자를 오른쪽으로 옮겨줘야 한다. 열쇠 위치에 도달했다가 다시 상자로 와야 하기 때문이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1895/submission/231136403&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1895/submission/231136403&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style8&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;B. &lt;span style=&quot;background-color: #ffffff; color: #222222; text-align: center;&quot;&gt;Points and Minimum Distance&lt;/span&gt; [00:06:58]&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;$x$와 $y$ 를 분리해서 생각해도 상관이 없고, $A$를 정렬하고 시작하자.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1차원인 경우에는 단순히 $A_{2N} - A_1$이 답이 되는데, 따라서 2차원인 경우에도 비슷하게 $A_{2N} - A_{N+1} + A_N - A_1$이 답이 된다. 따라서 정렬 후 앞의 원소 절반을 순서대로 방문할 점의 $x$좌표로, 뒤의 원소 절반을 방문할 점의 $y$좌표로 두면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1895/submission/231140864&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1895/submission/231140864&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style8&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C. Torn Lucky Ticket [00:21:24]&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;티켓 개수가 $200\ 000$개이기 때문에 자릿수 합이 같은 티켓을 묶어서 계산해야 하는 문제이다. 자릿수가 같은 티켓끼리 모으고 시작하자.&lt;br /&gt;1. 같은 티켓을 연속해서 붙이면 항상 조건을 만족한다. 따라서 답에는 항상 $N$이 더해지게 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. 두 티켓 $a$와 $b$가 있을 때, $a + b$는 조건을 만족할 수 있지만 $b + a$는 그렇지 않을 수 있다. 따라서 $|a| &amp;lt; |b|$인 경우와 $|a| &amp;gt; |b|$인 경우를 나눠서 각각 짜줘야 한다. 더 손이 안 가는 구현 방법이 있는지는 잘 모르겠다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;$|a| \neq |b|$인 경우의 구현에 대해서 짧게 메모하자면, $|a| &amp;lt; |b|$인 경우에는 $a$의 자릿수 합이 같은 것끼리 모아두고, $b$의 경우에는 $a$ 쪽에 붙어야 하는 자릿수 합과 나머지 자릿수 합을 pair로 저장하는 식으로 구현했다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1895/submission/231157035&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1895/submission/231157035&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style8&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D. XOR Construction [00:35:23, 0]&lt;/b&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;각 비트마다, $B$의 특정 비트가 켜져 있는지 안 켜져 있는지를 판단해줄 것이다. 이 여부는 $A_i$의 해당 비트가 켜져 있을 때마다 반전된다. 아래 표와 같은 느낌이다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 34px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;A&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;B&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 17px;&quot;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;$B$의 어떤 값의 해당 비트가 정확하게 켜져 있어야 하는지는 알 수 없지만, 적어도 어떤 연속된 값들이 같은 비트 상태를 가져야 한다는 사실은 위를 통해 알 수 있다. 같은 비트 상태를 가지는 연속된 값들을 &lt;b&gt;구간&lt;/b&gt;이라고 하자.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;홀수 번째 구간과 짝수 번째 구간 각각에 몇 개의 원소들이 들어가 있는지를 세자. 그리고 $[0, N)$ 구간의 값들 중 해당 비트가 켜져 있는 값의 수와 꺼져 있는 값의 수도 같이 세자. 홀수 번째 구간과 짝수 번째 구간 중, 비트가 켜져 있는 값의 수와 일치하는 쪽에 모두 해당 비트가 의미하는 값 ($2^k$) 만큼을 더해주면 된다.&amp;nbsp;&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;이제 이렇게 만든 배열 $B$가 모두 $[0, N)$ 사이 구간에 들어오도록 보정해줘야 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(홀수 번째 구간과 짝수 번째 구간에 포함되는 원소 수가 같을 때 배열 $B$가 유일하게 결정이 되지 않을 수 있기 때문에 보정을 해줘야 하는 경우가 생긴다. 구현 방식에 따라 다를 수 있겠지만, 나는 예제 2번이 그런 경우에 해당했다.)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;모든 비트에 대해, 배열 $B$에서 비트가 켜져 있는 값의 수와 $[0, N)$ 구간에서 비트가 켜져 있는 값의 수가 다르다면 $B$ 전체에 해당 비트가 의미하는 값을 xor 해주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1895/submission/231166173&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/contest/1895/submission/231166173&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;E. Inifinite Card Game [01:09:25, -1]&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Monocarp가 처음에 내는 카드의 공격력은 중요하지 않다. 처음에 내는 카드의 방어력만 중요하다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Monocarp와 Bicarp의 최적 전략은 동일하다. 상대가 낸 방어력보다 높은 공격력을 가지면서, 그 중 가장 방어력이 높은 카드를 내는 것이다. 따라서 한 사람이 어떤 카드를 냈을 때, 어떤 방어력을 가진 카드가 답신으로 돌아올지는 정해져 있다. 여기서 Functional Graph의 향기를 약간 느낄 수 있다.&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;카드의 공격력과 방어력을 싹 모아서 좌표 압축을 하고 시작하자. 그리고 Monocarp와 Bicarp가 낼 수 있는 모든 방어력에 대해, 해당 방어력을 가진 카드를 냈을 때 어떤 방어력을 가진 카드가 돌아올 지를 계산한다. 대충 계산을 하려면 공격력을 index로, 방어력을 value로 가지는 최대 세그먼트 트리를 이용해서 구할 수도 있고, 어차피 필요한 모든 쿼리가 $[k, SZ]$와 같이 Suffix Max 형태에 해당한다는 점을 이용하면 그냥 $O(N)$에 구해도 된다. 이 값들을 모두 구해두면 Functional Graph 형태를 하나 얻을 수 있다.&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;1. Functional Graph에서 DP를 한다. 중간에 사이클을 만나면 무승부, 마지막으로 이동한 간선이 Monocarp면 승리, Bicarp면 패배이다. 짜보진 않았지만 별로 쉽지 않을 것 같다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. 승패가 갈리는 구간이 단조성을 가진다는 점을 이용한다. $LLLLDDDDDWWWW$ 의 형태에서 $LD$에 해당하는 구간을 찾고, $DW$에 해당하는 구간을 각각 이분 탐색으로 찾는다. 이기고 지는 건 직접 Functional Graph를 따라가보면서 확인한다. 무승부 여부를 잘 처리해줘야 하는 것 같다.&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;$M$을 써야 하는 곳에 $N$을 썼다가 한 번 틀렸다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeforces.com/contest/1895/submission/231182104&quot;&gt;https://codeforces.com/contest/1895/submission/231182104&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;F. Fancy Arrays [Not Solved]&lt;/b&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;1. $||a_i - a_{i+1} \le K||$ 와 $a_i \le 0$을 만족하는 수열의 개수를 구한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 모든 값이 $[0, X)$ 구간에 있으면서, 조건을 만족하는 수열의 개수를 1에서 뺀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 모든 값이 $[X+K, INF)$ 구간에 있으면서, 조건을 만족하는 수열의 개수를 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;2에 해당하는 부분은 $X \le 40$ 이라는 점을 이용하면 대충 행렬 제곱으로 구할 수 있다. 1-3에 해당하는 값을 잘 구하는 게 관건이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-3을 다른 표현으로 정리하면, $[0, X+K)$ 구간의 수를 하나라도 포함하는 수열의 개수를 세는 문제가 된다. 이 개수는 $(X+K)^{2K-1}$ 이다. &lt;a href=&quot;https://codeforces.com/blog/entry/121963?#comment-1082794&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/blog/entry/121963?#comment-1082794&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;</description>
      <category>CodeForces</category>
      <author>IBory</author>
      <guid isPermaLink="true">https://bnb2011.tistory.com/4</guid>
      <comments>https://bnb2011.tistory.com/4#entry4comment</comments>
      <pubDate>Sat, 4 Nov 2023 12:03:58 +0900</pubDate>
    </item>
  </channel>
</rss>