<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>알고리즘 공부방</title>
    <link>https://arnold518.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 3 Aug 2026 13:47:30 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>arnold518</managingEditor>
    <item>
      <title>블로그 이전</title>
      <link>https://arnold518.tistory.com/123</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arnold518.github.io/ps-notes/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://arnold518.github.io/ps-notes/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688586718644&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;Problem Solving Notes&quot; data-og-description=&quot;&quot; data-og-host=&quot;arnold518.github.io&quot; data-og-source-url=&quot;https://arnold518.github.io/ps-notes/&quot; data-og-url=&quot;https://arnold518.github.io/ps-notes/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://arnold518.github.io/ps-notes/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arnold518.github.io/ps-notes/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Problem Solving Notes&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arnold518.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Github 블로그로 이전합니다!&lt;/p&gt;</description>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/123</guid>
      <comments>https://arnold518.tistory.com/123#entry123comment</comments>
      <pubDate>Thu, 6 Jul 2023 04:52:19 +0900</pubDate>
    </item>
    <item>
      <title>홀의 결혼 정리 (Hall's Marriage Theorem)</title>
      <link>https://arnold518.tistory.com/122</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://gazelle-and-cs.tistory.com/10&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;gazelle-and-cs.tistory.com/10&lt;/a&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;a href=&quot;https://en.wikipedia.org/wiki/Hall%27s_marriage_theorem&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;en.wikipedia.org/wiki/Hall%27s_marriage_theorem&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;이분그래프 $G=(L+R, E)$에서, $L$의 부분집합 $S$에 대해 이와 연결된 $R$의 부분집합을 $N(S)$라 하자.&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;이 이분그래프에서 L의 모든 정점이 참여하는 매칭이 존재할 필요충분조건은 모든 $S$에 대하여 $|S| \leq |N(S)|$ 가 성립하는 것이다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>그래프 이론 정리</category>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/122</guid>
      <comments>https://arnold518.tistory.com/122#entry122comment</comments>
      <pubDate>Mon, 15 Feb 2021 15:00:11 +0900</pubDate>
    </item>
    <item>
      <title>기본 용어 (Terminology)</title>
      <link>https://arnold518.tistory.com/121</link>
      <description>&lt;p&gt;1. Walk&lt;/p&gt;
&lt;p&gt;Sequence of vertices and edges of a graph.&lt;/p&gt;
&lt;p&gt;Vertex can be repeated.&lt;/p&gt;
&lt;p&gt;Edges can be repeated.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Open Walk : starting vertex != ending vertex&lt;/p&gt;
&lt;p&gt;Closed Walk : starting vertex == ending vertex&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2. Trail&lt;/p&gt;
&lt;p&gt;Open walk in which no edge is repeated.&lt;/p&gt;
&lt;p&gt;Vertex can be repeated.&lt;/p&gt;
&lt;p&gt;Edges cannot be repeated.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3. Circuit&lt;/p&gt;
&lt;p&gt;Closed walk in which no edge is repeated.&lt;/p&gt;
&lt;p&gt;Closed trail.&lt;/p&gt;
&lt;p&gt;Vertex can be repeated.&lt;/p&gt;
&lt;p&gt;Edges cannot be repeated.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;4. Path&lt;/p&gt;
&lt;p&gt;Trail in which neither vertices nor edges are repeated.&lt;/p&gt;
&lt;p&gt;Open walk.&lt;/p&gt;
&lt;p&gt;Vertex cannot be repeated.&lt;/p&gt;
&lt;p&gt;Edges cannot be repeated.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;5. Cycle&lt;/p&gt;
&lt;p&gt;Circuit which only the starting and ending vertices are repeated.&lt;/p&gt;
&lt;p&gt;Vertex cannot be repeated.&lt;/p&gt;
&lt;p&gt;Edges cannot be repeated.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>그래프 이론 정리</category>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/121</guid>
      <comments>https://arnold518.tistory.com/121#entry121comment</comments>
      <pubDate>Sat, 13 Feb 2021 18:07:30 +0900</pubDate>
    </item>
    <item>
      <title>DNC Opt / Monotone Queue Opt</title>
      <link>https://arnold518.tistory.com/120</link>
      <description>&lt;p&gt;&lt;b&gt;1. 모든 $a \leq b$, $c \leq d$에 대해, $f(a, c)+f(b, d) \leq f(a, d)+f(b, c)$가 성립한다면, $f(i, j)$는 사각 부등식 (Quadrangle Inequality), Monge Property를 만족한다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;$f(a, c)+f(b, d) \leq f(a, d)+f(b, c)$를 다음과 같이 해석할 수 있다. 구간 $[a, d]$와 $[b, c]$를 선택하는 대신에 구간 $[a, c]$와 $[b, d]$를 선택하도록 바꿔주는 것이 이득이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;2. $[l, r]$의 값들을 SUM한 함수와 MIN을 취한 함수는 Monge Property를 만족한다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;SUM 함수는 항상 $f(a, c)+f(b, d)=f(a, d)+f(b, c)$이니 성립한다.&lt;/p&gt;
&lt;p&gt;MIN 함수는 전체 구간에 대한 minimum 값이 $[b, c]$에 있다면 $f(a, c)+f(b, d)=f(a, d)+f(b, c)$를 만족한다.&lt;/p&gt;
&lt;p&gt;일반성을 잃지 않고 전체 구간에 대한 minimum 값이 $[a, b]$에 있다면 $f(a, c)$, $f(a, d)$는 이 minimum 값을 선택하고, 남은 $f(b, d)$, $f(b, c)$값 중 범위가 $f(b, d)$가 더 넓으니 $f(b, d) \leq f(b, c)$가 성립해, 준 식이 성립한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;3. 각 $r$마다 $f(l, r)$이 최소인 값 중 가장 왼쪽인 $l$값을 $opt(r)$이라 한다면 $opt(r)$은 단조 증가한다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;단조 증가하지 않고, $p \leq q$이지만, $a=opt(p) \geq b=opt(q)$인 $p, q$가 존재한다 가정하자.&lt;/p&gt;
&lt;p&gt;opt의 정의에 따라 $f(a, p) \leq f(b, p)$, $f(a, q) \geq f(b, q)$가 성립한다.&lt;/p&gt;
&lt;p&gt;두 식을 더하면 $f(a, p)+f(b, q) \leq f(b, p)+f(a, q)$이고, 이는 Monge Property에 모순이다.&lt;/p&gt;
&lt;p&gt;즉, $a \leq b$이고, $opt(r)$은 단조 증가 함수이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;4. 1사분면에 단조 감소하는 점들의 집합 P와, 3사분면에 단조 감소하는 점들의 집합 Q가 있을 때, P의 점 하나와 Q의 점 하나를 이용하여 만들 수 있는 직사각형의 넓이를 $f(i, j)$이라 할 때, $f(i, j)$는 Monge Property를 만족한다. (ICPC WF Money For Nothing)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;5. $dp(i, k)=min_{j&amp;lt;i}{dp(j, k-1)+f(j, i)}$로 정의될 때 각 $i$마다 $dp(i, k)$를 최소로 하는 값 중 가장 왼쪽인 $j$값을 $opt(i)$이라 한다면 $opt(i)$는 단조 증가한다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;증명 과정은 위 3과 동일하다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;6. 5번 성질을 이용하여 Divide &amp;amp; Conquer을 이용하면 문제를 $O(NKlogN)$에 해결할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;$solve(l1, r1, l2, r2)$은 $[l1, r1]$의 모든 $dp(i, k)$값을 구하는 함수이다. $[l1, r1]$의 opt값의 후보가 되는 구간이 $[l2, r2]$이니, 가운데 값인 mid1의 opt를 구한 후, 이를 이용하여 $solve(l1, mid1-1, l2, mid2)$, $solve(mid1+1, r1, mid2, r2)$를 구해주면 된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;7. $p \leq q$, $i \leq j$일 때, $dp(p)+f(p, i) \geq dp(q)+f(q, i)$라면 $dp(p)+f(p, j) \geq dp(q)+f(q, j)$이다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;$p \leq q$, $i \leq j$일 때, $dp(p)+f(p, j) \leq dp(q)+f(q, j)$라면 $dp(p)+f(p, i) \leq dp(q)+f(q, i)$이다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;$dp(p)+f(p, i) \geq dp(q)+f(q, i)$이고, $dp(p)+f(p, j) \leq dp(q)+f(q, j)$라 가정하자.&lt;/p&gt;
&lt;p&gt;두 식을 더하면 $f(p, i)+f(q, j) \geq f(q, i)+f(p, j)$이고, 이는 Monge Property에 모순이다.&lt;/p&gt;
&lt;p&gt;위 성질을 이용하여 특정 $x$를 기준으로 $i \leq x$에 대해, $dp(p)+f(p, i) \leq dp(q)+f(q, i)$, 즉 $p$가 더 최적이며, $i &amp;gt; x$에 대해, $dp(p)+f(p, i) \geq dp(q)+f(q, i)$, 즉 $q$가 더 최적이다.&lt;/p&gt;
&lt;p&gt;$p$, $q$에 대해서만 본다면 $g_p(x)=dp(p)+f(p, x)$라 정의했을 때, $g_p(x)$는 일차함수와 비슷한 성질을 가짐을 의미한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;8. 7번 성질을 이용하여 $dp(i)=min_{j&amp;lt;i}{dp(j)+f(j, i)}$를 $O(NlogN)$에 해결할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;두 함수 $p \leq q$ $g_p(x)$, $g_q(x)$에 대해, 두 함수의 대소관계가 갈리는 특정 $x$를 $cross(p, q)$라 하자.&lt;/p&gt;
&lt;p&gt;$cross(p, q)$를 구하는 과정은 단순한 이분탐색을 통해 $O(logN)$에 계산해줄 수 있다.&lt;/p&gt;
&lt;p&gt;스택에 $p \leq q \leq r$이라면 $cross(p, q) \leq cross(q, r)$이 성립하도록 스택에 함수들을 뒤에서부터 삽입한다.&lt;/p&gt;
&lt;p&gt;이 과정은 일차함수들을 스택에 관리하는 CHT와 동일하다.&lt;/p&gt;
&lt;p&gt;이후 앞에서부터 더이상 opt의 범위를 벗어난 일차함수들을 제거해주는 과정을 거치면, 가장 앞쪽의 함수가 최적의 함수이다.&lt;/p&gt;
&lt;p&gt;전체 과정은 Deque를 이용하여 $O(NlogN)$에 관리할 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;9. 7번 성질을 이용하여 $g_p(x)$를 단순 일차함수로 취급하여 일반적인 CHT나, Li Chao Tree 등의 자료구조를 응용하여 활용할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>아이디어 &amp;amp; 테크닉 모음</category>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/120</guid>
      <comments>https://arnold518.tistory.com/120#entry120comment</comments>
      <pubDate>Sun, 7 Feb 2021 22:37:20 +0900</pubDate>
    </item>
    <item>
      <title>KMP 알고리즘</title>
      <link>https://arnold518.tistory.com/119</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://blog.naver.com/kks227/220917078260&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;blog.naver.com/kks227/220917078260&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1612248606021&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;KMP 알고리즘(Knuth&amp;ndash;Morris&amp;ndash;Pratt Algorithm) (수정: 2019-09-01)&quot; data-og-description=&quot;KMPlayer가 아니다 안녕하세요. 한동안 그래프를 줄창 했듯이 이제부터는 문자열을 줄창 하게 될 겁니다...&quot; data-og-host=&quot;blog.naver.com&quot; data-og-source-url=&quot;https://blog.naver.com/PostView.nhn?blogId=kks227&amp;amp;logNo=220917078260&amp;amp;categoryNo=299&amp;amp;parentCategoryNo=299&amp;amp;viewDate=&amp;amp;currentPage=1&amp;amp;postListTopCurrentPage=&amp;amp;from=postList&amp;amp;userTopListOpen=true&amp;amp;userTopListCount=30&amp;amp;userTopListManageOpen=false&amp;amp;userTopListCurrentPage=1&quot; data-og-url=&quot;https://blog.naver.com/kks227/220917078260&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cIPlH6/hyI8RkNuJe/8uELQqm9xzzgn3dCAaFAE1/img.png?width=743&amp;amp;height=107&amp;amp;face=0_0_743_107,https://scrap.kakaocdn.net/dn/b32lSj/hyI8VOhHpM/qJbMr5onSuRXdFksTOWid0/img.png?width=560&amp;amp;height=336&amp;amp;face=0_0_560_336&quot;&gt;&lt;a href=&quot;https://blog.naver.com/PostView.nhn?blogId=kks227&amp;amp;logNo=220917078260&amp;amp;categoryNo=299&amp;amp;parentCategoryNo=299&amp;amp;viewDate=&amp;amp;currentPage=1&amp;amp;postListTopCurrentPage=&amp;amp;from=postList&amp;amp;userTopListOpen=true&amp;amp;userTopListCount=30&amp;amp;userTopListManageOpen=false&amp;amp;userTopListCurrentPage=1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.naver.com/PostView.nhn?blogId=kks227&amp;amp;logNo=220917078260&amp;amp;categoryNo=299&amp;amp;parentCategoryNo=299&amp;amp;viewDate=&amp;amp;currentPage=1&amp;amp;postListTopCurrentPage=&amp;amp;from=postList&amp;amp;userTopListOpen=true&amp;amp;userTopListCount=30&amp;amp;userTopListManageOpen=false&amp;amp;userTopListCurrentPage=1&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cIPlH6/hyI8RkNuJe/8uELQqm9xzzgn3dCAaFAE1/img.png?width=743&amp;amp;height=107&amp;amp;face=0_0_743_107,https://scrap.kakaocdn.net/dn/b32lSj/hyI8VOhHpM/qJbMr5onSuRXdFksTOWid0/img.png?width=560&amp;amp;height=336&amp;amp;face=0_0_560_336');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;KMP 알고리즘(Knuth&amp;ndash;Morris&amp;ndash;Pratt Algorithm) (수정: 2019-09-01)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;KMPlayer가 아니다 안녕하세요. 한동안 그래프를 줄창 했듯이 이제부터는 문자열을 줄창 하게 될 겁니다...&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;blog.naver.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;13.png&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;248&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/83AXu/btqVug1yNWg/ZY08TlYhG24ckQP5kybrdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/83AXu/btqVug1yNWg/ZY08TlYhG24ckQP5kybrdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/83AXu/btqVug1yNWg/ZY08TlYhG24ckQP5kybrdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F83AXu%2FbtqVug1yNWg%2FZY08TlYhG24ckQP5kybrdK%2Fimg.png&quot; data-filename=&quot;13.png&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;248&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$S[1, i]$ 에서 prefix와 suffix가 같은 최대 길이를 fail[i]라 저장한 전처리 배열을 먼저 만든다.&lt;/p&gt;
&lt;p&gt;그 후, 위 그림과 같이 불일치가 발생하였을 때마다, fail에 해당하는 값만큼 건너뛰어, i는 절대 감소하지 않고, j만 이동하도록 만들어 주면 시간복잡도가 $O(N+M)$이 보장된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;fail 함수를 구하는 방법은 단순히 위 알고리즘을 S에서 S를 탐색하는 방향으로 바꾸고, 일치가 발생할 때마다 fail함수에 현재 i위치에 대한 j위치를 기록해주면 된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1612248547365&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

typedef long long ll;
typedef pair&amp;lt;int, int&amp;gt; pii;
typedef pair&amp;lt;ll, ll&amp;gt; pll;

const int MAXN = 1e6;

string SS, TT;
int N, M;
char S[MAXN+10], T[MAXN+10];

int fail[MAXN+10];

int main()
{
	getline(cin, SS);
	getline(cin, TT);

	N=SS.size(); M=TT.size();
	for(int i=1; i&amp;lt;=N; i++) S[i]=SS[i-1];
	for(int i=1; i&amp;lt;=M; i++) T[i]=TT[i-1];

	for(int i=2, j=1; i&amp;lt;=M;)
	{
		if(T[i]!=T[j] || j&amp;gt;M)
		{
			if(j==1) i++;
			else j=fail[j-1]+1;
		}
		else
		{
			fail[i]=j;
			i++; j++;
		}
	}

	vector&amp;lt;int&amp;gt; ans;
	for(int i=1, j=1; i&amp;lt;=N;)
	{
		if(S[i]!=T[j] || j&amp;gt;M)
		{
			if(j==1) i++;
			else j=fail[j-1]+1;
		}
		else
		{
			i++; j++;
			if(j&amp;gt;M) ans.push_back(i-M);
		}
	}
	printf(&quot;%d\n&quot;, ans.size());
	for(auto it : ans) printf(&quot;%d &quot;, it);
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘 &amp;amp; 자료구조 정리</category>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/119</guid>
      <comments>https://arnold518.tistory.com/119#entry119comment</comments>
      <pubDate>Tue, 2 Feb 2021 15:49:09 +0900</pubDate>
    </item>
    <item>
      <title>2021/02/01 ~ 2020/02/07</title>
      <link>https://arnold518.tistory.com/118</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;2021/02/01&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/10128&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;www.acmicpc.net/problem/10128&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1612205538042&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;10128번: Supercomputer&quot; data-og-description=&quot;In the first line of standard input, there are two integers, n and q(1 &amp;le; n,q &amp;le; 1,000,000), separated by a single space, that specify the number of instructions in Byteasar's program and the number of running time queries (for different numbers of proce&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/10128&quot; data-og-url=&quot;https://www.acmicpc.net/problem/10128&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/DVKwK/hyI80uJCEq/b6gjbBfiFNocSJ4vbSl9Mk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bOeCvI/hyI853SyaO/JwGEtUwu6urjRE9PmfhGt1/img.png?width=359&amp;amp;height=399&amp;amp;face=0_0_359_399&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/10128&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/10128&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/DVKwK/hyI80uJCEq/b6gjbBfiFNocSJ4vbSl9Mk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bOeCvI/hyI853SyaO/JwGEtUwu6urjRE9PmfhGt1/img.png?width=359&amp;amp;height=399&amp;amp;face=0_0_359_399');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;10128번: Supercomputer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;In the first line of standard input, there are two integers, n and q(1 &amp;le; n,q &amp;le; 1,000,000), separated by a single space, that specify the number of instructions in Byteasar's program and the number of running time queries (for different numbers of proce&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://arnold518.tistory.com/117&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;arnold518.tistory.com/117&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/20172&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;www.acmicpc.net/problem/20172&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1612205595615&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;20172번: Electric Vehicle&quot; data-og-description=&quot;Your program is to read from standard input. The input starts with an integer n (2 &amp;le; n &amp;le; 1,000), representing the number of villages. Each of the following n lines contains three integers, a, b, and c (0 &amp;le; a, b &amp;le; 106 and 1 &amp;le; c &amp;le; 104), where (a,&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/20172&quot; data-og-url=&quot;https://www.acmicpc.net/problem/20172&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dxsa0U/hyI80VOZ1E/GroMkfV5a59SbyTXdcKbMK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bh2jSb/hyI84qpdKd/uu4tXDgV7hBk04faPefKq1/img.png?width=502&amp;amp;height=434&amp;amp;face=0_0_502_434&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/20172&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/20172&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dxsa0U/hyI80VOZ1E/GroMkfV5a59SbyTXdcKbMK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bh2jSb/hyI84qpdKd/uu4tXDgV7hBk04faPefKq1/img.png?width=502&amp;amp;height=434&amp;amp;face=0_0_502_434');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;20172번: Electric Vehicle&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;Your program is to read from standard input. The input starts with an integer n (2 &amp;le; n &amp;le; 1,000), representing the number of villages. Each of the following n lines contains three integers, a, b, and c (0 &amp;le; a, b &amp;le; 106 and 1 &amp;le; c &amp;le; 104), where (a,&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2021/02/02&lt;/h2&gt;
&lt;p&gt;NOI(China) 2014&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17309&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;www.acmicpc.net/problem/17309&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1612290542950&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;17309번: Enchanted Forest&quot; data-og-description=&quot;To obtain the master calligrapher's true teachings, little E has decided to pay a visit to the hermit of an enchanted forest. The forest can be represented as an undirected graph with&amp;nbsp;n&amp;nbsp;nodes and&amp;nbsp;m&amp;nbsp;edges. The nodes are numbered 1, 2, 3, &amp;hellip;,&amp;nbsp;n&amp;nbsp;and th&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/17309&quot; data-og-url=&quot;https://www.acmicpc.net/problem/17309&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d6YqTo/hyJabvBFAw/MXeOtx5pCYkKyCykeh4hn0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17309&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/17309&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d6YqTo/hyJabvBFAw/MXeOtx5pCYkKyCykeh4hn0/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;&gt;17309번: Enchanted Forest&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;To obtain the master calligrapher's true teachings, little E has decided to pay a visit to the hermit of an enchanted forest. The forest can be represented as an undirected graph with&amp;nbsp;n&amp;nbsp;nodes and&amp;nbsp;m&amp;nbsp;edges. The nodes are numbered 1, 2, 3, &amp;hellip;,&amp;nbsp;n&amp;nbsp;and th&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS(공부) 일지</category>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/118</guid>
      <comments>https://arnold518.tistory.com/118#entry118comment</comments>
      <pubDate>Tue, 2 Feb 2021 03:53:19 +0900</pubDate>
    </item>
    <item>
      <title>POI14 Supercomputer</title>
      <link>https://arnold518.tistory.com/117</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/10128&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;www.acmicpc.net/problem/10128&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1612197868176&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;10128번: Supercomputer&quot; data-og-description=&quot;In the first line of standard input, there are two integers, n and q(1 &amp;le; n,q &amp;le; 1,000,000), separated by a single space, that specify the number of instructions in Byteasar's program and the number of running time queries (for different numbers of proce&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/10128&quot; data-og-url=&quot;https://www.acmicpc.net/problem/10128&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/DVKwK/hyI80uJCEq/b6gjbBfiFNocSJ4vbSl9Mk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bOeCvI/hyI853SyaO/JwGEtUwu6urjRE9PmfhGt1/img.png?width=359&amp;amp;height=399&amp;amp;face=0_0_359_399&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/10128&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/10128&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/DVKwK/hyI80uJCEq/b6gjbBfiFNocSJ4vbSl9Mk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bOeCvI/hyI853SyaO/JwGEtUwu6urjRE9PmfhGt1/img.png?width=359&amp;amp;height=399&amp;amp;face=0_0_359_399');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;10128번: Supercomputer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;In the first line of standard input, there are two integers, n and q(1 &amp;le; n,q &amp;le; 1,000,000), separated by a single space, that specify the number of instructions in Byteasar's program and the number of running time queries (for different numbers of proce&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;루트가 정해진 트리가 하나 주어지고, 트리의 각 노드는 프로세스로, 어떤 노드의 프로세스를 실행하기 위해서는 그 노드의 조상 노드를 모두 실행해야 한다.&lt;/p&gt;
&lt;p&gt;이때, 한번에 K개의 프로세스를 동시에 실행할 수 있으며, 전체 실행 단계를 최소화해야한다.&lt;/p&gt;
&lt;p&gt;트리는 하나로 고정되어 주어지고, K값이 쿼리로 들어온다.&lt;/p&gt;
&lt;p&gt;$N&amp;lt;=10^6, Q&amp;lt;=10^6$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;노드 $u$에 대해, 루트에서 그 노드까지의 거리를 $d(u)$, 그 노드에서 자식으로 갈 수 있는 최대 길이를 $h(u)$라 정의하자.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Observation 1 : 트리의 높이를 $h(1)$, 노드의 개수를 $N$개라고 했을 때 답은 $\lceil \frac{N}{K} \rceil$ 이상이고, $h(1)$이상이다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;한번에 선택할 수 있는 노드의 수가 최대 K개이기 때문에 답은 $\lceil \frac{N}{K} \rceil$이상이고, 또한 1번 정점으로부터 가장 깊이가 깊은 노드까지의 길이 $h(1)$의 경로를 생각하면 한 단계당 경로의 노드를 최대 한개씩만 선택할 수 있기 떄문에 $h(1)$이상이다.&lt;/p&gt;
&lt;p&gt;이 관찰을 통해서 답을 결정하는 요소에는 노드의 개수도 있지만, 트리의 깊이 또한 중요하다는 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Observation 2 : 각 단계에서 선택할 수 있는 노드들 중, $h(u)$가 가장 큰 노드들부터 선택하는 것이 최적의 전략이다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;기본적으로 지금 $h(u)$를 선택했다면 현재 단계를 포함해서 앞으로 적어도 $h(u)$개의 추가 단계가 필요하다는 것을 의미하니, 가장 추후에 드는 단계가 많이 필요한 노드부터 선택해야 할 필요가 있다. 엄밀한 증명은 다음의 관찰을 한 후에 증명한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;한번의 단계에 최대한 많이 선택을 해야 하는데, 최대 K씩만 선택할 수 있기 때문에 거꾸로 K개 선택할 수 없는 단계에 주목하자. K보다 적게 선택했다는 것은 현재 선택할 수 있는 노드가 K개 미만이라는 것이고, K개 선택했다는 것은 현재 선택할 수 있는 노드의 수가 K개 이상임을 의미한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$r_k(t)$를 K개씩 선택하는 알고리즘에서 t번째 단계에서 선택하는 노드의 수로 정의하자.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Observation 3 : Observation 2의 알고리즘에 따라 선택한다면 $r_k(t)&amp;lt;K$라면 $d(u)&amp;lt;=t$인 모든 노드들이 t단계 전까지 모두 선택되어 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;귀납법을 이용하여 증명한다.&lt;/p&gt;
&lt;p&gt;$r_k(1)=1&amp;lt;K$ 일 때는 $d(u)&amp;lt;=1$인 u는 루트 하나밖에 없으니, 성립한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$r_k(t)&amp;lt;K$라 하자. 만약 $r_k(t-1)=K$라면, 귀납적으로 $d(u)&amp;lt;=t-1$인 모든 노드들은 선택되었고, 이로 인해 $d(u)=t$인 노드들은 모두 잠금 해제 되었다. 또한, t-1단계까지는 깊이가 t-1인 노드만 선택할 수 있기 때문에, 이 외의 다른 노드들은 선택할 수 없다. 따라서 현재 선택할 수 있는 노드들은 오직 깊이가 t인 노드 전부이며, $r_k(t)&amp;lt;K$이니, 선택할 수 있는 모든 노드를 선택하여 깊이 $t$인 모든 노드를 선택한다. 따라서 귀납 조건을 만족한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이제 $r_k(t-1)=K$이고, 더 나아가 $r_k(t-1)=K$인 노드가 연속하여 $B$개 있다고 하자.&lt;/p&gt;
&lt;p&gt;귀납 가정을 만족하지 않는다고 가정하자. 즉, $r_k(t)&amp;lt;K$이지만 깊이 t의 노드들 중 선택되지 않은 정점 u가 존재한다고 가정하자. u의 B개 조상을 건너뛴 노드 v는 $r_k(t-B-1)&amp;lt;K$이기 때문에 귀납 가정에 의해 선택되었을 것이다. 따라서 v 다음의 노드는 B개가 있지만, u는 시간 t까지도 선태되지 않았기 때문에 B-1개 이하의 노드들이 그 사이에 선택되었을 것이다. 그렇다면, u의 조상 집합에 있는 노드들 중 아무것도 선택하지 않게 되는 단계 p가 존재하고, $r_k(p)=K$이다. 그 단계에서 u의 조상 집합이 아닌 다른 노드를 선택했다는 것은, 최소한 깊이가 t이상인 서로 다른 노드가 K개 존재한다는 것이고, 그러한 노드들을 해당 단계에서 선택했다는 것이다. 하지만 이가 의미하는 것은 p이후의 모든 단계에서 각 노드들의 자식들을 하나씩 선택했다고 가정해도 t번째 단계까지 왔을 때 선택할 수 있는 노드가 K개는 존재한다는 것이다. 하지만 단계 t에서는 노드를 K개 미만으로밖에 선택하지 못했으니, 모순이다. 즉 귀납 조건은 성립한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Observation 3를 이용하여 Observation 2의 알고리즘이 최적의 전략임을 증명하자.&lt;/p&gt;
&lt;p&gt;먼저 Observation 2의 알고리즘으로 선택을 진행한 후, $r_k(t)&amp;lt;K$인 최대의 t를 p라 하자. 전체 노드들을 깊이 p이하와, 초과로 나누어 각 단계에서 Observation 2의 알고리즘의 선택보다 최적의 선택이 없음을 보이자.&lt;/p&gt;
&lt;p&gt;p개의 단계로는 최대 깊이 p이하의 노드들만 선택할 수 있기 때문에 깊이 p이하의 노드들을 정확히 p단계를 이용하여 모두 선택했다면, 이보다 더 적게 선택할 수 있는 방법은 없다. 깊이가 p초과인 노드들에 대해서는 모두 $r_k(t)=K$이니, 한번에 선택할 수 있는 모든 노드들을 다 선택한 것이니, 이보다 더 적게 선택할 수는 없다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이제, 최적의 전략을 찾았으니 위 전략을 그대로 priority queue를 이용하여 시뮬레이션해주면 각 쿼리당 $O(NlogN)$의 시간복잡도에 해결할 수 있어, 전체 $O(QNlogN)$에 해결할 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;마지막 Observation 2의 증명 과정을 다시 생각해보면 답의 형태가 매우 간단한 꼴로 요약됨을 알 수 있다.&lt;/p&gt;
&lt;p&gt;t이상($t'&amp;gt;=t$)의 $r_k(t')$ 들의 합을 $sum_t$라 정의하자.&lt;/p&gt;
&lt;p&gt;$r_k(t)&amp;lt;K$인 최대의 t를 찾아 이를 p라 한다면 답은 $p+\lceil \frac{sum_{p+1}}{K} \rceil$이다.&lt;/p&gt;
&lt;p&gt;하지만 시뮬레이션을 해보기 전까지 해당 p를 정확히 알지 못한다는 문제가 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Observation 4 : p보다 작거나, p보다 큰 모든 t에 대해 $t+\lceil \frac{sum_{t+1}}{K} \rceil$값은 모두 p에 대한 값보다 작다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;먼저, $p+\lceil \frac{sum_{p+1}}{K} \rceil$ 대신, $p+\frac{sum_{p+1}}{K}$을 구하고, 이 값에 ceil을 씌우자.&lt;/p&gt;
&lt;p&gt;만약 t가 p보다 작을 경우, $p-t$와 $\frac{sum_{t+1}}{K}-\frac{sum_{p+1}}{K}$를 비교하면, $\frac{r_k(t+1)+r_k(t+2)+ ... +r_k(p)}{K}$이고, $r_k(t')&amp;lt;=K$이니, $\frac{r_k(t+1)+r_k(t+2)+ ... +r_k(p)}{K}&amp;lt;=\frac{(p-t)K}{K}=p-t$이니, p에대한 값이 t에대한 값보다 작거나 같다.&lt;/p&gt;
&lt;p&gt;만약 t가 p보다 클 경우, p 이후의 $r_k(t)=K$이니, p에 대한 값이 t에 대한 값과 같다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;즉, 굳이 p를 몰라도 단순히 $t+\lceil \frac{sum_{t+1}}{K} \rceil$값을 최대화하면 된다.&lt;/p&gt;
&lt;p&gt;sum 함수의 정의 또한 같은 논리로 실제 시뮬레이션 과정에서의 t이상($t'&amp;gt;=t$)의 $r_k(t')$ 들의 합 대신, 높이 t+1 이상의 노드들의 수로 정의할 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이제 쿼리로 들어오는 K에 대해 $\frac{Kt+sum_{t+1}}{K}$을 최대화 하면 되기 때문에, 분자에 있는 값은 K에 대한 일차함수임을 이용해 CHT를 이용하여 해결한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;시간 복잡도 : $O(N+QlogN)$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1612205235193&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

typedef long long ll;
typedef pair&amp;lt;int, int&amp;gt; pii;
typedef pair&amp;lt;ll, ll&amp;gt; pll;

const int MAXN = 1e6;

int N, Q;
int A[MAXN+10];

int dep[MAXN+10];
vector&amp;lt;int&amp;gt; adj[MAXN+10];
int B[MAXN+10];

void dfs(int now, int d)
{
	dep[now]=d;
	for(int nxt : adj[now])
	{
		dfs(nxt, d+1);
	}
}

struct Line
{
	ll a, b;
};

double cross(Line p, Line q) { return (double)(p.b-q.b)/(q.a-p.a); }

struct CHT
{
	vector&amp;lt;Line&amp;gt; S;
	void push(Line p)
	{
		while(S.size()&amp;gt;1 &amp;amp;&amp;amp; cross(S[S.size()-2], S[S.size()-1])&amp;gt;cross(S[S.size()-1], p)) S.pop_back();
		S.push_back(p);
	}
	ll query(ll x)
	{
		int lo=0, hi=S.size();
		while(lo+1&amp;lt;hi)
		{
			int mid=lo+hi&amp;gt;&amp;gt;1;
			if(cross(S[mid], S[mid-1])&amp;lt;=x) lo=mid;
			else hi=mid;
		}
		return S[lo].a*x+S[lo].b;
	}
}cht;

int main()
{
	scanf(&quot;%d%d&quot;, &amp;amp;N, &amp;amp;Q);
	for(int i=1; i&amp;lt;=Q; i++) scanf(&quot;%d&quot;, &amp;amp;A[i]);
	for(int i=2; i&amp;lt;=N; i++)
	{
		int u, v=i;
		scanf(&quot;%d&quot;, &amp;amp;u);
		adj[u].push_back(i);
	}
	dfs(1, 1);

	for(int i=1; i&amp;lt;=N; i++) B[dep[i]]++;
	for(int i=N; i&amp;gt;=1; i--) B[i]+=B[i+1];

	for(int i=1; i&amp;lt;=N; i++)
	{
		if(B[i]==0) break;
		cht.push({i, B[i+1]});
		//printf(&quot;%d %d\n&quot;, i, B[i+1]);
	}
	for(int i=1; i&amp;lt;=Q; i++)
	{
		int K=A[i];
		ll t=cht.query(K)+K-1;
		t/=K;
		printf(&quot;%lld\n&quot;, t);
	}
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>POI/2014</category>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/117</guid>
      <comments>https://arnold518.tistory.com/117#entry117comment</comments>
      <pubDate>Tue, 2 Feb 2021 03:20:40 +0900</pubDate>
    </item>
    <item>
      <title>dm.cpp</title>
      <link>https://arnold518.tistory.com/116</link>
      <description>&lt;pre id=&quot;code_1611644727355&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

typedef long long ll;
typedef pair&amp;lt;int, int&amp;gt; pii;
typedef pair&amp;lt;ll, ll&amp;gt; pll;

mt19937 rng(chrono::high_resolution_clock().now().time_since_epoch().count());
ll rand(ll l, ll r) { return uniform_int_distribution&amp;lt;ll&amp;gt;(l, r)(rng); }

void compile()
{
	system(&quot;g++ -std=c++17 -O2 -o PROBLEM grader.cpp PROBLEM.cpp&quot;);
	system(&quot;g++ -std=c++17 -O2 -o PROBLEM2 grader.cpp PROBLEM2.cpp&quot;);
}

void input()
{
	FILE *in=fopen(&quot;in&quot;, &quot;w&quot;);
	fclose(in);
}

vector&amp;lt;char&amp;gt; read(char *S)
{
	FILE *out=fopen(S, &quot;r&quot;);
	char c; vector&amp;lt;char&amp;gt; V;
	c=getc(out);
	while(c!=EOF)
	{
		V.push_back(c);
		c=getc(out);
	}
	fclose(out);
	return V;
}

bool run()
{
	system(&quot;./PROBLEM &amp;lt;in &amp;gt;out&quot;);
	system(&quot;./PROBLEM2 &amp;lt;in &amp;gt;out2&quot;);
	return read(&quot;out&quot;)==read(&quot;out2&quot;);
}

int main()
{
	compile();
	for(int tc=1; ; tc++)
	{
		printf(&quot;TC %d\n&quot;, tc);
		input();
		if(!run()) break;
	}
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Study</category>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/116</guid>
      <comments>https://arnold518.tistory.com/116#entry116comment</comments>
      <pubDate>Tue, 26 Jan 2021 16:05:30 +0900</pubDate>
    </item>
    <item>
      <title>Centroid Decomposition</title>
      <link>https://arnold518.tistory.com/115</link>
      <description>&lt;p&gt;&lt;b&gt;1. 문제에서 구하고 싶은 구조 (트리에서의 경로 / 트리에서의 연속 컴포넌트)를 루트를 정해놓고, 그 루트를 지나는 것들만 고려했을 때 쉽게 풀 수 있다면 Centroid Decomposition을 이용하여 전체 문제를 해결할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;만약 트리에서의 루트가 고정되어 있고, 루트를 지나는 구조들에 대해서는 쉽게 풀 수 있다면, 이제 그 루트를 지나지 않는 경우에 대해서는 Centroid Decomposition의 분할정복 과정에서 다음으로 탐색할 것이다.&lt;/p&gt;
&lt;p&gt;이와 같이 생각하면 장점이, 루트를 지나는 경로 / 컴포넌트 등은 각 서브트리에서 문제를 독립적으로 해결할 수 있으니, 가능한 모든 정점쌍 / 집합쌍을 고려하는 대신, 한 서브트리의 정점들을 자료구조 안에 삽입한 후 다른 정점들을 빠르게 찾을 수도 있고, 독립적인 상황으로 만들어 빠르게 전처리한 후 해결할 수 있다.&lt;/p&gt;
&lt;p&gt;이 때 주의해야할 점은 루트를 무조건 지나도록 해야하기 때문에, 양쪽 방향으로 스위핑을 하는 등의 작업이 필요할 수도 있다.&lt;/p&gt;
&lt;p&gt;이러한 성질 때문에 특히, 트리에서의 거리함수와 관련된 내용이 나왔을 때 쉽게 적용할 수 있다.&lt;/p&gt;</description>
      <category>아이디어 &amp;amp; 테크닉 모음</category>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/115</guid>
      <comments>https://arnold518.tistory.com/115#entry115comment</comments>
      <pubDate>Fri, 22 Jan 2021 15:01:29 +0900</pubDate>
    </item>
    <item>
      <title>JOISC18 Bitaro</title>
      <link>https://arnold518.tistory.com/114</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://oj.uz/problem/view/JOI18_bitaro&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;oj.uz/problem/view/JOI18_bitaro&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1611293989499&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;문제 보기 - Bitaro&amp;rsquo;s Party (JOI18_bitaro) :: oj.uz&quot; data-og-description=&quot;문제 보기 - Bitaro&amp;rsquo;s Party (JOI18_bitaro)&quot; data-og-host=&quot;oj.uz&quot; data-og-source-url=&quot;https://oj.uz/problem/view/JOI18_bitaro&quot; data-og-url=&quot;https://oj.uz/problem/view/JOI18_bitaro&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://oj.uz/problem/view/JOI18_bitaro&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://oj.uz/problem/view/JOI18_bitaro&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;문제 보기 - Bitaro&amp;rsquo;s Party (JOI18_bitaro) :: oj.uz&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;문제 보기 - Bitaro&amp;rsquo;s Party (JOI18_bitaro)&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;oj.uz&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;정점 개수 N, 간선 개수 M개의 DAG가 주어진다. 이 때, 다음과 같은 쿼리에 답해야 한다.&lt;/p&gt;
&lt;p&gt;정점 v로 오는 경로들 중, 시작점이 u1, u2, ..., uk 중 하나인 경로들을 제외했을 때 최장경로의 길이룰 구하라.&lt;/p&gt;
&lt;p&gt;$N&amp;lt;=100000$&lt;/p&gt;
&lt;p&gt;$M&amp;lt;=200000$&lt;/p&gt;
&lt;p&gt;$Q&amp;lt;=100000$&lt;/p&gt;
&lt;p&gt;$\sum K_i&amp;lt;=100000$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;풀이&lt;/h2&gt;
&lt;p&gt;Naive한 방법은 각 쿼리마다, 시작점으로 불가능한 정점들을 모두 체크해놓고, DP를 새로 돌리며 새로운 최장경로를 찾는 것이다. 각 쿼리에 $O(N+M)$의 시간이 들어, 전체 시간복잡도는 $O(Q(N+M))$이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;일반적인 DAG에서의 최장경로의 길이는 dp를 통해 계산해줄 수 있다.&lt;/p&gt;
&lt;p&gt;이와 같은 아이디어로, 만약 시작점이 막힌 정점이 몇개 없다면, 이를 K번째 최단경로를 구하는 문제로 바꾸어 해결할 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;만약 $K_i&amp;lt;=K$라면, 각 정점에서 시작점이 서로 다른 1~K+1번째 최장경로들의 길이를 구해놓는다면, 막힌 정점을 모두 제거하고도, 위에서 구한 경로들 중에 답이 존재하게 된다. 이를 계산하는데 드는 시간은 DP를 이용하면 $O((N+M)KlogK)$이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;위에서 K가 작을 때 잘 동작하는 알고리즘을 발견하였고, K의 합의 상한이 정해져 있으므로, sqrt decomposition을 이용한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;먼저 $K=\sqrt{100000}$에 대해서 위 K+1번째 최장경로 DP를 돌린다.&lt;/p&gt;
&lt;p&gt;$K_i$가 $\sqrt{100000}$보다 작은 경우, 위에서 전처리한 값을 이용하여 답을 구한다.&lt;/p&gt;
&lt;p&gt;$K_i$가 $\sqrt{100000}$보다 큰 경우, 그 개수가 $\sqrt{100000}$보다 작으니, Naive한 알고리즘을 이용하여 답을 구한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;시간 복잡도 : $O(Q+(N+M)logN\sqrt{100000})$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1611294816897&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
 
typedef long long ll;
typedef pair&amp;lt;int, int&amp;gt; pii;
typedef pair&amp;lt;ll, ll&amp;gt; pll;
 
const int MAXN = 2e5;
const int SQ = 100;
const int INF = 1e9;
 
int N, M, Q;
vector&amp;lt;int&amp;gt; adj[MAXN+10];
int ans[MAXN+10];
int dp[MAXN+10];
int val[MAXN+10];
 
struct Data
{
	int T, P;
	vector&amp;lt;int&amp;gt; V;
};
Data A[MAXN+10];
vector&amp;lt;int&amp;gt; P[MAXN+10];
 
vector&amp;lt;pii&amp;gt; dp2[MAXN+10];
bool chk[MAXN+10];
 
int main()
{
	memset(ans, -1, sizeof(ans));
	scanf(&quot;%d%d%d&quot;, &amp;amp;N, &amp;amp;M, &amp;amp;Q);
	for(int i=1; i&amp;lt;=M; i++)
	{
		int u, v;
		scanf(&quot;%d%d&quot;, &amp;amp;u, &amp;amp;v);
		adj[v].push_back(u);
	}
	for(int i=1; i&amp;lt;=Q; i++)
	{
		int a, b;
		scanf(&quot;%d%d&quot;, &amp;amp;a, &amp;amp;b);
		A[i].T=a; A[i].P=i;
		while(b--)
		{
			int t;
			scanf(&quot;%d&quot;, &amp;amp;t);
			A[i].V.push_back(t);
		}
 
		if(A[i].V.size()&amp;gt;=SQ)
		{
			for(int j=1; j&amp;lt;=N; j++) dp[j]=0;
			for(auto it : A[i].V) dp[it]=-INF;
			for(int j=1; j&amp;lt;=N; j++) for(auto nxt : adj[j]) dp[j]=max(dp[j], dp[nxt]+1);
			if(dp[A[i].T]&amp;gt;=0) ans[i]=dp[A[i].T];
		}
		else P[A[i].T].push_back(i);
	}
 
	for(int now=1; now&amp;lt;=N; now++)
	{
		dp2[now].push_back({0, now});
		vector&amp;lt;int&amp;gt; V;
		for(auto nxt : adj[now])
		{
			for(auto it : dp2[nxt])
			{
				val[it.second]=max(val[it.second], it.first+1);
				V.push_back(it.second);
			}
		}
		
		for(auto it : V)
		{
			if(chk[it]) continue;
			chk[it]=true;
			dp2[now].push_back({val[it], it});
		}
		for(auto it : V) chk[it]=false;
		sort(dp2[now].begin(), dp2[now].end(), greater&amp;lt;pii&amp;gt;());
		while(dp2[now].size()&amp;gt;SQ) dp2[now].pop_back();
		for(auto it : V) val[it]=0;
 
		for(auto it : dp2[now]) chk[it.second]=false;
		for(auto it : P[now])
		{
			for(auto pt : A[it].V) chk[pt]=true;
			for(auto jt : dp2[now])
			{
				if(!chk[jt.second])
				{
					ans[it]=jt.first;
					break;
				}
			}
			for(auto pt : A[it].V) chk[pt]=false;
		}
	}
 
	for(int i=1; i&amp;lt;=Q; i++) printf(&quot;%d\n&quot;, ans[i]);
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>JOISC/2018</category>
      <author>arnold518</author>
      <guid isPermaLink="true">https://arnold518.tistory.com/114</guid>
      <comments>https://arnold518.tistory.com/114#entry114comment</comments>
      <pubDate>Fri, 22 Jan 2021 14:53:40 +0900</pubDate>
    </item>
  </channel>
</rss>