<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Atcoder Study</title><description>Solutions of AtCoder problems and brief explanations for study.</description><link>https://zeikar.dev/atcoder/</link><language>ko-KR</language><item><title>ABC_166_E - This Message Will Self-Destruct in 5s</title><link>https://zeikar.dev/atcoder/posts/82/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/82/</guid><description>배열에서 두 원소를 선택할 때 값의 합이 인덱스의 차이의 절댓값이 되는 경우의 수를 구하는 문제. 뭔가 수학적인 것이 보일 듯 해서 정리를 해봤다. j &gt; i로 고정하고 절댓값을 풀면 j - Aj = i + Ai 가 되는데 i + Ai가 몇개인지 계속 더해주면서 j에 대해 j - Aj 개수를 더해주면 된다. 참고:</description><pubDate>Sun, 02 Oct 2022 07:42:28 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc166/tasks/abc166_e&quot;&gt;https://atcoder.jp/contests/abc166/tasks/abc166_e&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;배열에서 두 원소를 선택할 때 값의 합이 인덱스의 차이의 절댓값이 되는 경우의 수를 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;뭔가 수학적인 것이 보일 듯 해서 정리를 해봤다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Ai + Aj == | j - i |
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;j &gt; i로 고정하고 절댓값을 풀면 j - Aj = i + Ai 가 되는데 i + Ai가 몇개인지 계속 더해주면서 j에 대해 j - Aj 개수를 더해주면 된다.&lt;/p&gt;
&lt;p&gt;참고: &lt;a href=&quot;https://codeforces.com/blog/entry/76833?#comment-614685&quot;&gt;https://codeforces.com/blog/entry/76833?#comment-614685&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;map&gt;
using namespace std;

int a[200000];
map&amp;#x3C;int, int&gt; diff;

int main() {
	int n;
	cin &gt;&gt; n;

	long long res = 0;
	for (int i = 0; i &amp;#x3C; n; i++)
	{
		cin &gt;&gt; a[i];

		res += diff[i - a[i]];
		diff[a[i] + i]++;
	}


	cout &amp;#x3C;&amp;#x3C; res &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_178_E - Dist Max</title><link>https://zeikar.dev/atcoder/posts/81/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/81/</guid><description>x, y 좌표가 주어질 때 가장 먼 맨해튼 거리를 구하는 문제. 일단 유명한 문제라고 하는데... 처음 대회에서는 풀지 못했다... 다시 천천히 해보면 어렵지 않은 문제이긴 하다 먼저 조건을 잘 써보면,| xi - xj | + | yi - yj |의 최댓값을 찾는 문제인데 절댓값을 벗겨준 후 정리해줄 수 있다. xi &gt; xj, yi &gt; yj (xi - xj…</description><pubDate>Sat, 01 Jan 2022 13:54:47 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc178/tasks/abc178_e&quot;&gt;https://atcoder.jp/contests/abc178/tasks/abc178_e&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;x, y 좌표가 주어질 때 가장 먼 맨해튼 거리를 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;일단 유명한 문제라고 하는데... 처음 대회에서는 풀지 못했다...&lt;/p&gt;
&lt;p&gt;다시 천천히 해보면 어렵지 않은 문제이긴 하다&lt;/p&gt;
&lt;p&gt;먼저 조건을 잘 써보면,&lt;code&gt;| xi - xj | + | yi - yj |&lt;/code&gt;의 최댓값을 찾는 문제인데 절댓값을 벗겨준 후 정리해줄 수 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;xi &gt; xj, yi &gt; yj&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(xi - xj) + (yi - yj)&lt;br&gt;
(xi + yi) - (xj + yj)&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;xi &amp;#x3C; xj, yi &gt; yj&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;-(xi - xj) + (yi - yj)&lt;br&gt;
-(xi - yi) + (xj - yj)&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;xi &gt; xj, yi &amp;#x3C; yj&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(xi - xj) - (yi - yj)&lt;br&gt;
(xi - yi) - (xj - yj)&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;xi &amp;#x3C; xj, yi &amp;#x3C; yj&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;-(xi - xj) - (yi - yj)&lt;br&gt;
-(xi + yi) + (xj + yj)&lt;/p&gt;
&lt;p&gt;잘 보면 양쪽이 (xj + yj) 또는 (xj - yj) 형식으로 정리가 되는데 x, y값의 합 또는 x, y의 값의 차를 전부 구하고 그중에 최대가 되도록 해주면 된다.&lt;/p&gt;
&lt;p&gt;따라서 정답은 &lt;code&gt;max( max(xi + yi) - min(xi + yi), max(xi - yi) - min(xi - yi) )&lt;/code&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;climits&gt;
using namespace std;

int main() {
	int n;
	cin &gt;&gt; n;

	int maxPlus = -INT_MAX;
	int minPlus = INT_MAX;
	int maxMinus = -INT_MAX;
	int minMinus = INT_MAX;
	for (int i = 0; i &amp;#x3C; n; i++)
	{
		int x, y;
		cin &gt;&gt; x &gt;&gt; y;

		int plus = x + y;
		int minus = x - y;

		maxPlus = max(maxPlus, plus);
		minPlus = min(minPlus, plus);
		maxMinus = max(maxMinus, minus);
		minMinus = min(minMinus, minus);
	}

	cout &amp;#x3C;&amp;#x3C; max(maxPlus - minPlus, maxMinus - minMinus) &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_231 - Panasonic Programming Contest 2021(AtCoder Beginner Contest 231)</title><link>https://zeikar.dev/atcoder/posts/80/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/80/</guid><description>A, B, C, D A, B, C: 간단 D: 결론만 말하면 연결된 곳이 3개 이상이거나 사이클이 있을 경우 No가 출력되어야 한다. 불친절한 예제로 직접 예외 케이스를 찾아야 한다. 엄청난 삽질.. 끝에 dsu로 풀긴 풀었다.</description><pubDate>Sat, 11 Dec 2021 13:49:47 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-contest-link&quot;&gt;Contest Link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc231&quot;&gt;https://atcoder.jp/contests/abc231&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-solved-problems&quot;&gt;Solved problems&lt;/h1&gt;
&lt;p&gt;A, B, C, D&lt;/p&gt;
&lt;h1 id=&quot;user-content-brief-explanations&quot;&gt;Brief explanations&lt;/h1&gt;
&lt;p&gt;A, B, C: 간단&lt;br&gt;
D: 결론만 말하면 연결된 곳이 &lt;strong&gt;3개 이상&lt;/strong&gt;이거나 &lt;strong&gt;사이클&lt;/strong&gt;이 있을 경우 No가 출력되어야 한다.&lt;br&gt;
불친절한 예제로 직접 예외 케이스를 찾아야 한다.&lt;br&gt;
엄청난 삽질.. 끝에 dsu로 풀긴 풀었다.&lt;/p&gt;</content:encoded><category>rated</category></item><item><title>ABC_191_C - Digital Graffiti</title><link>https://zeikar.dev/atcoder/posts/79/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/79/</guid><description>그리드에 #, .으로 이루어진 문자열이 주어질 때 이 도형이 몇각형인지 구하는 문제. 문제 설명, 예제가 불친절한데... 오목 다각형도 존재할 수 있다. 어쨌든 다각형이 몇각형인지 구하려면 꼭지점의 개수를 구해야 한다. 이건 에디토리얼을 참고했는데 상하좌우 2칸씩 개수를 세서 검은색 블록 (#)이 1개 또는 3개이면 꼭지점이다. 예시를 보면 좀 이해가 가긴…</description><pubDate>Thu, 09 Dec 2021 13:07:39 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc191/tasks/abc191_c&quot;&gt;https://atcoder.jp/contests/abc191/tasks/abc191_c&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;그리드에 &lt;code&gt;#&lt;/code&gt;, &lt;code&gt;.&lt;/code&gt;으로 이루어진 문자열이 주어질 때 이 도형이 몇각형인지 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;문제 설명, 예제가 불친절한데... &lt;strong&gt;오목 다각형&lt;/strong&gt;도 존재할 수 있다.&lt;/p&gt;
&lt;p&gt;어쨌든 다각형이 몇각형인지 구하려면 &lt;strong&gt;꼭지점의 개수&lt;/strong&gt;를 구해야 한다.&lt;br&gt;
이건 에디토리얼을 참고했는데 &lt;strong&gt;상하좌우 2칸씩 개수를 세서 검은색 블록 (&lt;code&gt;#&lt;/code&gt;)이 1개 또는 3개이면 꼭지점&lt;/strong&gt;이다.&lt;/p&gt;
&lt;p&gt;예시를 보면 좀 이해가 가긴 하는데&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.....
.###.
.###.
.###.
.....
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이건 4각형이고&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.....
.#.#.
.###.
.###.
.....
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이건 8각형이 된다&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;string&gt;
using namespace std;

int main() {
	int h, w;
	cin &gt;&gt; h &gt;&gt; w;

	string grid[10];

	for (int i = 0; i &amp;#x3C; h; i++)
	{
		cin &gt;&gt; grid[i];
	}

	int ans = 0;

	for (int i = 0; i &amp;#x3C; h - 1; i++)
	{
		for (int j = 0; j &amp;#x3C; w - 1; j++)
		{
			int cnt = 0;

			for (int a = 0; a &amp;#x3C; 2; a++)
			{
				for (int b = 0; b &amp;#x3C; 2; b++)
				{
					cnt += (grid[i + a][j + b] == &apos;#&apos;);
				}
			}

			if (cnt == 1 || cnt == 3)
			{
				ans++;
			}
		}
	}

	cout &amp;#x3C;&amp;#x3C; ans &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_223_D - Restricted Permutation</title><link>https://zeikar.dev/atcoder/posts/78/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/78/</guid><description>1부터 N까지 순열 중에 Ai의 위치 &lt; Bi의 위치를 만족시키는 사전 순으로 가장 작은 순열을 구하는 문제. 잘 보니 위상 정렬 문제이다. 사전 순으로 출력해야 하므로 우선순위 큐로 처리해주고 정답 사이즈가 n이 아니면 사이클이 존재하는 것이므로 -1을 출력하면 된다.</description><pubDate>Sat, 04 Dec 2021 15:15:23 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc223/tasks/abc223_d&quot;&gt;https://atcoder.jp/contests/abc223/tasks/abc223_d&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;1부터 N까지 순열 중에 &lt;code&gt;Ai의 위치 &amp;#x3C; Bi의 위치&lt;/code&gt;를 만족시키는 사전 순으로 가장 작은 순열을 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;잘 보니 &lt;strong&gt;위상 정렬&lt;/strong&gt; 문제이다.&lt;/p&gt;
&lt;p&gt;사전 순으로 출력해야 하므로 &lt;strong&gt;우선순위 큐&lt;/strong&gt;로 처리해주고 정답 사이즈가 n이 아니면 사이클이 존재하는 것이므로 -1을 출력하면 된다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;vector&gt;
#include &amp;#x3C;queue&gt;
using namespace std;

vector&amp;#x3C;int&gt; edges[200001];
int indegree[200001];

int main() {
	int n, m;

	cin &gt;&gt; n &gt;&gt; m;

	while (m--)
	{
		int a, b;
		cin &gt;&gt; a &gt;&gt; b;

		edges[a].push_back(b);
		++indegree[b];
	}

	priority_queue&amp;#x3C;int&gt; que;
	queue&amp;#x3C;int&gt; ans;
	for (int i = 1; i &amp;#x3C;= n; i++)
	{
		if (indegree[i] == 0)
		{
			que.push(-i);
		}
	}

	while (!que.empty())
	{
		int node = -que.top();
		que.pop();
		ans.push(node);

		for (int i = 0; i &amp;#x3C; edges[node].size(); i++)
		{
			int next = edges[node][i];

			indegree[next]--;

			if (indegree[next] == 0)
			{
				que.push(-next);
			}
		}
	}

	if (ans.size() != n)
	{
		cout &amp;#x3C;&amp;#x3C; -1 &amp;#x3C;&amp;#x3C; endl;
	}
	else
	{
		while (!ans.empty())
		{
			cout &amp;#x3C;&amp;#x3C; ans.front() &amp;#x3C;&amp;#x3C; &apos; &apos;;
			ans.pop();
		}
		cout &amp;#x3C;&amp;#x3C; endl;
	}
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_192_E - Train</title><link>https://zeikar.dev/atcoder/posts/77/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/77/</guid><description>도시들이 있고 철도의 정보 (소요 시간, 출발하는 시각)이 주어질 때 x 에서 y로 가는 최소 시간을 구하는 문제. 전형적인 다익스트라 문제이다. 단, 기차가 ki 의 배수로만 출발하므로 이를 보정하기 위해 ki 배수 미만이면 ki 배수로 만들고 ti를 더하도록 하였다.</description><pubDate>Sat, 04 Dec 2021 14:31:30 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc192/tasks/abc192_e&quot;&gt;https://atcoder.jp/contests/abc192/tasks/abc192_e&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;도시들이 있고 철도의 정보 (소요 시간, 출발하는 시각)이 주어질 때  x 에서 y로 가는 최소 시간을 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;전형적인 &lt;strong&gt;다익스트라&lt;/strong&gt; 문제이다.&lt;br&gt;
단, 기차가 ki 의 배수로만 출발하므로 이를 보정하기 위해 ki 배수 미만이면 ki 배수로 만들고 ti를 더하도록 하였다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;vector&gt;
#include &amp;#x3C;queue&gt;
#include &amp;#x3C;tuple&gt;
#include &amp;#x3C;climits&gt;
using namespace std;

class Edge
{
public:
	Edge(int dest, int t, int k) {
		this-&gt;dest = dest;
		this-&gt;t = t;
		this-&gt;k = k;
	}

	int dest;
	int t;
	int k;
};

vector&amp;#x3C;Edge&gt; edges[100001];
long long distances[100001];

int main() {
	int n, m, x, y;
	cin &gt;&gt; n &gt;&gt; m &gt;&gt; x &gt;&gt; y;

	for (int i = 0; i &amp;#x3C;= n; i++)
	{
		distances[i] = LLONG_MAX;
	}

	while (m--)
	{
		int a, b, t, k;
		cin &gt;&gt; a &gt;&gt; b &gt;&gt; t &gt;&gt; k;

		edges[a].push_back(Edge(b, t, k));
		edges[b].push_back(Edge(a, t, k));
	}

	priority_queue&amp;#x3C;tuple&amp;#x3C;long long, int&gt; &gt; pq;
	pq.push(make_tuple(0, x));
	distances[x] = 0;

	while (!pq.empty())
	{
		auto current = pq.top();
		pq.pop();

		long long currentTime = -get&amp;#x3C;0&gt;(current);
		int currentCity = get&amp;#x3C;1&gt;(current);

		if (distances[currentCity] &amp;#x3C; currentTime)
		{
			continue;
		}

		for (int i = 0; i &amp;#x3C; edges[currentCity].size(); i++)
		{
			auto nextEdge = edges[currentCity][i];
			long long nextTime;

			if (currentTime % nextEdge.k == 0)
			{
				nextTime = currentTime + nextEdge.t;
			}
			else
			{
				nextTime = ((currentTime / nextEdge.k) + 1) * nextEdge.k + nextEdge.t;
			}

			if (distances[nextEdge.dest] &amp;#x3C;= nextTime)
			{
				continue;
			}
			distances[nextEdge.dest] = nextTime;

			pq.push(make_tuple(-nextTime, nextEdge.dest));
		}
	}

	if (distances[y] == LLONG_MAX)
	{
		cout &amp;#x3C;&amp;#x3C; -1 &amp;#x3C;&amp;#x3C; endl;
	}
	else
	{
		cout &amp;#x3C;&amp;#x3C; distances[y] &amp;#x3C;&amp;#x3C; endl;
	}
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_230_D - Destroyer Takahashi</title><link>https://zeikar.dev/atcoder/posts/76/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/76/</guid><description>모든 벽을 부수기 위해 최소 몇 번 펀치를 해야 하는지 구하는 문제. 모든 벽을 부숴야 하므로 정렬 후 왼쪽부터 쭉 나가면 될 것 같다. 근데 이게 생각보다 안돼서... 대회 중에 결국 못 풀었다 에디토리얼을 참고해서 재작성. 일단 정렬은 맞는데 오른쪽 좌표를 기준으로 정렬해야 한다. 해당 벽을 제거할 때 최대한 오른쪽을 제거해야 다른 벽도 같이 제거할 수…</description><pubDate>Fri, 03 Dec 2021 14:14:43 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc230/tasks/abc230_d&quot;&gt;https://atcoder.jp/contests/abc230/tasks/abc230_d&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;모든 벽을 부수기 위해 최소 몇 번 펀치를 해야 하는지 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;모든 벽을 부숴야 하므로 정렬 후 왼쪽부터 쭉 나가면 될 것 같다.&lt;br&gt;
근데 이게 생각보다 안돼서... 대회 중에 결국 못 풀었다&lt;/p&gt;
&lt;p&gt;에디토리얼을 참고해서 재작성.&lt;/p&gt;
&lt;p&gt;일단 정렬은 맞는데 &lt;strong&gt;오른쪽 좌표를 기준으로 정렬&lt;/strong&gt;해야 한다. 해당 벽을 제거할 때 &lt;strong&gt;최대한 오른쪽을 제거&lt;/strong&gt;해야 다른 벽도 같이 제거할 수 있기 때문이다.&lt;br&gt;
제거하는 벽은 왼쪽 좌표가 제거할 좌표 + d - 1 이내이면 가능하다.&lt;br&gt;
이 좌표를 넘어가면 한번에 부술 수 없으므로 다시 오른쪽 좌표에서 펀치를 날려야 한다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;algorithm&gt;
#include &amp;#x3C;utility&gt;
#include &amp;#x3C;queue&gt;
#include &amp;#x3C;vector&gt;
using namespace std;

int main() {
	int n, d;
	cin &gt;&gt; n &gt;&gt; d;

	vector&amp;#x3C; pair&amp;#x3C;int, int&gt; &gt; walls;

	for (int i = 1; i &amp;#x3C;= n; i++)
	{
		int l, r;
		cin &gt;&gt; l &gt;&gt; r;

		walls.push_back(make_pair(r, l));
	}

	sort(walls.begin(), walls.end());

	int ans = 0, x = -1987654321;
	for (int i = 0; i &amp;#x3C; walls.size(); i++)
	{
		int l = walls[i].second;
		int r = walls[i].first;

		if (l &gt; x + d - 1)
		{
			ans++;

			x = r;
		}
	}

	cout &amp;#x3C;&amp;#x3C; ans &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_230 - AtCoder Beginner Contest 230</title><link>https://zeikar.dev/atcoder/posts/75/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/75/</guid><description>A, B, C A, B: 간단 C: 칠해지는 좌표의 규칙을 알면 된다. i-j, i+j 값을 이용하면 칠해지는 위치인지 판별 가능하다.</description><pubDate>Fri, 03 Dec 2021 14:09:49 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-contest-link&quot;&gt;Contest Link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc230&quot;&gt;https://atcoder.jp/contests/abc230&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-solved-problems&quot;&gt;Solved problems&lt;/h1&gt;
&lt;p&gt;A, B, C&lt;/p&gt;
&lt;h1 id=&quot;user-content-brief-explanations&quot;&gt;Brief explanations&lt;/h1&gt;
&lt;p&gt;A, B: 간단&lt;br&gt;
C: 칠해지는 좌표의 규칙을 알면 된다. i-j, i+j 값을 이용하면 칠해지는 위치인지 판별 가능하다.&lt;/p&gt;</content:encoded><category>rated</category></item><item><title>ABC_228 - TOYOTA SYSTEMS Programming Contest 2021(AtCoder Beginner Contest 228)</title><link>https://zeikar.dev/atcoder/posts/74/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/74/</guid><description>A, B, C, D A, B 간단. 단, A는 처음에 이해가 안되서 1번 틀림... C: 정렬을 한 후 자신보다 300점 높은 개수를 세고 K보다 작거나 같으면 Yes 출력. 개수를 셀 때 upper bound 이용. D: 들어갈 수 있는 자리를 map으로 예약해두고 값이 업데이트 될 때마다 제거, 자리를 찾는 건 lower bound 이용. 단, n을 넘…</description><pubDate>Sat, 20 Nov 2021 14:28:30 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-contest-link&quot;&gt;Contest Link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc228&quot;&gt;https://atcoder.jp/contests/abc228&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-solved-problems&quot;&gt;Solved problems&lt;/h1&gt;
&lt;p&gt;A, B, C, D&lt;/p&gt;
&lt;h1 id=&quot;user-content-brief-explanations&quot;&gt;Brief explanations&lt;/h1&gt;
&lt;p&gt;A, B 간단. 단, A는 처음에 이해가 안되서 1번 틀림...&lt;br&gt;
C: 정렬을 한 후 자신보다 300점 높은 개수를 세고 K보다 작거나 같으면 Yes 출력. 개수를 셀 때 upper bound 이용.&lt;br&gt;
D: 들어갈 수 있는 자리를 map으로 예약해두고 값이 업데이트 될 때마다 제거, 자리를 찾는 건 lower bound 이용. 단, n을 넘으면 다시 0부터 채워야 하므로 2 * n 만큼을 자리 예약을 해둠.&lt;/p&gt;</content:encoded><category>rated</category></item><item><title>ABC_080_C - Shopping Street</title><link>https://zeikar.dev/atcoder/posts/73/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/73/</guid><description>상점을 오픈하는데, 특정 시간에 다른 상점이 열린 개수에 따라 최대로 만들 수 있는 이익을 구하는 문제. Fij : i 상점이 j 시간에 열려 있는지 여부. Pij : i 상점이 j 시간만큼 열린 시간이 겹쳤을 때 얻을 수 있는 이익. 처음에 문제 자체를 이해하기 좀 어려웠는데 계속 보니까 대략 머리에 들어왔다. 일단, Joisino가 상점을 열지 말지 두…</description><pubDate>Sat, 20 Nov 2021 14:23:07 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc080/tasks/abc080_c&quot;&gt;https://atcoder.jp/contests/abc080/tasks/abc080_c&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;상점을 오픈하는데, 특정 시간에 다른 상점이 열린 개수에 따라 최대로 만들 수 있는 이익을 구하는 문제.&lt;br&gt;
Fij : i 상점이 j 시간에 열려 있는지 여부.&lt;br&gt;
Pij : i 상점이 j 시간만큼 열린 시간이 겹쳤을 때 얻을 수 있는 이익.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;처음에 문제 자체를 이해하기 좀 어려웠는데 계속 보니까 대략 머리에 들어왔다.&lt;/p&gt;
&lt;p&gt;일단, Joisino가 상점을 열지 말지 두 가지 방법이 있고 시간이 총 10개 있으므로 단순 2^10 탐색을 해주면 된다.&lt;/p&gt;
&lt;p&gt;상점을 열었을 경우 그 시점에 다른 상점이 열려있는 개수를 카운트 하고 더해주면 되는 간단한 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
using namespace std;

int f[100][10];
int p[100][11];

int main() {
	int n;
	cin &gt;&gt; n;

	for (int i = 0; i &amp;#x3C; n; i++)
	{
		for (int j = 0; j &amp;#x3C; 10; j++)
		{
			cin &gt;&gt; f[i][j];
		}
	}

	for (int i = 0; i &amp;#x3C; n; i++)
	{
		for (int j = 0; j &amp;#x3C; 11; j++)
		{
			cin &gt;&gt; p[i][j];
		}
	}

	int ans = -1987654321;
	for (int i = 1; i &amp;#x3C; (1 &amp;#x3C;&amp;#x3C; 10); i++)
	{
		int profit = 0;

		for (int j = 0; j &amp;#x3C; n; j++)
		{
			int cnt = 0;

			for (int k = 0; k &amp;#x3C; 10; k++)
			{
				// open
				if (i &amp;#x26; (1 &amp;#x3C;&amp;#x3C; k) &amp;#x26;&amp;#x26; f[j][k] == 1)
				{
					cnt++;
				}
			}

			profit += p[j][cnt];
		}

		ans = max(ans, profit);
	}

	cout &amp;#x3C;&amp;#x3C; ans &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ARC_091_B / ABC_090_D - Remainder Reminder</title><link>https://zeikar.dev/atcoder/posts/72/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/72/</guid><description>N을 넘지 않는 a, b 쌍 중에서 a % b가 K 보다 크거나 같은 개수를 구하는 문제. 예제 1에 힌트가 있는데, b에 대해 K + 1부터 N까지 다 돌려가면서 나머지가 K 이상이 되는 a의 개수를 구해주면 된다. N % b를 r로 두면, a가 r 이하인 경우엔 N / b + 1번 가능하고 r보다 큰 경우는 N / b번만 가능하다. K == 0일 땐, …</description><pubDate>Fri, 19 Nov 2021 08:49:15 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/arc091/tasks/arc091_b&quot;&gt;https://atcoder.jp/contests/arc091/tasks/arc091_b&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;N을 넘지 않는 a, b 쌍 중에서 a % b가 K 보다 크거나 같은 개수를 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;예제 1에 힌트가 있는데, &lt;strong&gt;b에 대해 K + 1부터 N까지 다 돌려가면서 나머지가 K 이상이 되는 a의 개수&lt;/strong&gt;를 구해주면 된다.&lt;/p&gt;
&lt;p&gt;N % b를 r로 두면, a가 r 이하인 경우엔 N / b + 1번 가능하고 r보다 큰 경우는 N / b번만 가능하다.&lt;/p&gt;
&lt;p&gt;K == 0일 땐, a == 0인 경우를 처리하기 위해 결과에서 N을 빼주면 된다. (문제에서 positive integers 라고 했으므로)&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
using namespace std;

int main() {
	int n, k;

	cin &gt;&gt; n &gt;&gt; k;

	long long res = 0;
	for (int b = k + 1; b &amp;#x3C;= n; b++)
	{
		// k to b-1
		int cnt = b - k;
		res += cnt * (n / b);

		res += max(0, n % b - k + 1);
	}

	if (k == 0)
	{
		res -= n;
	}

	cout &amp;#x3C;&amp;#x3C; res &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_226 - AtCoder Beginner Contest 226</title><link>https://zeikar.dev/atcoder/posts/71/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/71/</guid><description>A, B, C, D A, B: 간단 C: 그냥 dfs 탐색해주면 된다. D: x, y 모든 쌍에 대해 좌표의 차이 (기울기)를 gcd로 나눠서 중복을 제거하면서 저장하면 된다.</description><pubDate>Sun, 07 Nov 2021 14:05:19 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-contest-link&quot;&gt;Contest Link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc226&quot;&gt;https://atcoder.jp/contests/abc226&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-solved-problems&quot;&gt;Solved problems&lt;/h1&gt;
&lt;p&gt;A, B, C, D&lt;/p&gt;
&lt;h1 id=&quot;user-content-brief-explanations&quot;&gt;Brief explanations&lt;/h1&gt;
&lt;p&gt;A, B: 간단&lt;br&gt;
C: 그냥 dfs 탐색해주면 된다.&lt;br&gt;
D: x, y 모든 쌍에 대해 좌표의 차이 (기울기)를 gcd로 나눠서 중복을 제거하면서 저장하면 된다.&lt;/p&gt;</content:encoded><category>rated</category></item><item><title>ABC_140_D - Face Produces Unhappiness</title><link>https://zeikar.dev/atcoder/posts/70/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/70/</guid><description>사람들이 L, R 방향을 바라보며 서 있고, 서로 같은 방향을 바라보면 happy이다. 이때 k 번의 횟수만큼 (l, r) 범위의 사람들의 방향을 뒤집을 수 있다. 최대로 happy 하게 만들 수 있는 사람의 수를 구하는 문제. 딱 보면 어려운데 포인트를 잘 알아채면 굉장히 쉬워지는 문제. 위 사실을 알면 쉽게 풀린다. 먼저 간단한 증명은 LLL ... R…</description><pubDate>Wed, 03 Nov 2021 14:33:02 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc140/tasks/abc140_d&quot;&gt;https://atcoder.jp/contests/abc140/tasks/abc140_d&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;사람들이 L, R 방향을 바라보며 서 있고, 서로 같은 방향을 바라보면 happy이다.&lt;br&gt;
이때 k 번의 횟수만큼 (l, r) 범위의 사람들의 방향을 뒤집을 수 있다.&lt;br&gt;
최대로 happy 하게 만들 수 있는 사람의 수를 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;딱 보면 어려운데 포인트를 잘 알아채면 굉장히 쉬워지는 문제.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;unhappy한 사람들을 뒤집게 되면 happy 하게 변하는 사람의 수는 2명이다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 사실을 알면 쉽게 풀린다.&lt;/p&gt;
&lt;p&gt;먼저 간단한 증명은 LLL ... RRR ... LLL 이 있을 때 R 을 뒤집어서 L로 만든다고 해보자. 그렇게 되면 RRR...R 의 &lt;strong&gt;내부의 happy는 그대로&lt;/strong&gt; 이고 LR ... RL 처럼 서로 경계에 있는 unhappy인 사람은 LL....LL로 뒤집어 지면서 &lt;strong&gt;총 2명의 happy 가 추가&lt;/strong&gt;된다.&lt;br&gt;
또한, 배열의 양쪽 끝부분을 뒤집으면 1명만 증가하지만 그리디 하게 2명 증가하는 부분만 뒤집는다고 생각하면 된다.&lt;/p&gt;
&lt;p&gt;최대로 happy할 수 있는 사람의 수는 n-1 이므로 이를 넘지 않도록 출력해주면 된다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;string&gt;
using namespace std;

int main() {
	int n, k;
	string s;

	cin &gt;&gt; n &gt;&gt; k &gt;&gt; s;

	int happy = 0;
	for (int i = 1; i &amp;#x3C; n; i++)
	{
		if (s[i] == s[i - 1])
		{
			happy++;
		}
	}

	cout &amp;#x3C;&amp;#x3C; min(n - 1, happy + 2 * k) &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>CODEFESTIVAL_2016_QUALA_C - Next Letter</title><link>https://zeikar.dev/atcoder/posts/69/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/69/</guid><description>문자열과 k가 주어진다. k번 연산을 통해 만들 수 있는 사전 순으로 가장 작은 수를 구하는 문제. 연산: 다음 문자로 변경, 단 z는 a로 변함. 일단 그리디 적으로 생각해보면 사전 순으로 최소가 되려면 앞 문자를 최대한 a로 만들어야 한다. a로 만들 수 없으면 아예 연산을 안 하는 것이 낫다. 위 두 규칙에 맞게 문자열을 돌면서 계산해주면 된다. 단,…</description><pubDate>Fri, 29 Oct 2021 11:51:43 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/code-festival-2016-quala/tasks/codefestival_2016_qualA_c&quot;&gt;https://atcoder.jp/contests/code-festival-2016-quala/tasks/codefestival_2016_qualA_c&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;문자열과 k가 주어진다. k번 연산을 통해 만들 수 있는 사전 순으로 가장 작은 수를 구하는 문제.&lt;br&gt;
연산: 다음 문자로 변경, 단 z는 a로 변함.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;일단 그리디 적으로 생각해보면&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;사전 순으로 최소가 되려면 &lt;strong&gt;앞 문자를 최대한 a로 만들어야&lt;/strong&gt; 한다.&lt;/li&gt;
&lt;li&gt;a로 만들 수 없으면 &lt;strong&gt;아예 연산을 안 하는 것이 낫다.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;위 두 규칙에 맞게 문자열을 돌면서 계산해주면 된다. 단, 연산 횟수가 남았을 경우 맨 마지막 문자를 수정하면 사전 순으로 최소가 되게 할 수 있다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;string&gt;
using namespace std;

int main() {
	string s;
	int k;
	cin &gt;&gt; s &gt;&gt; k;

	for (int i = 0; i &amp;#x3C; s.size(); i++)
	{
		if (s[i] == &apos;a&apos;)
		{
			continue;
		}

		int diff = 26 - (s[i] - &apos;a&apos;);
		// possible to change to a
		if (k &gt;= diff)
		{
			s[i] = &apos;a&apos;;
			k -= diff;
		}
	}

	// remains
	s[s.size() - 1] = ((s[s.size() - 1] - &apos;a&apos;) + k % 26) % 26 + &apos;a&apos;;

	cout &amp;#x3C;&amp;#x3C; s &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_194_D - Journey</title><link>https://zeikar.dev/atcoder/posts/68/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/68/</guid><description>n개의 정점으로 이루어진 그래프가 있다. 현재는 그래프의 1번에 있는데 1/n 확률로 다른 정점을 선택할 수 있다. 이때 모든 정점을 선택하게 되는 시도 횟수의 기댓값을 구하는 문제. 위 블로그를 참고함. 일단, 성공 확률을 p 라고 할 때, 성공할 때까지 수행 할 때의 시도 횟수는 확률의 역수(1/p)가 된다. 라는 사실을 알아야 풀 수 있는 문제. 증명…</description><pubDate>Wed, 27 Oct 2021 15:37:18 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc194/tasks/abc194_d&quot;&gt;https://atcoder.jp/contests/abc194/tasks/abc194_d&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;n개의 정점으로 이루어진 그래프가 있다.&lt;br&gt;
현재는 그래프의 1번에 있는데 1/n 확률로 다른 정점을 선택할 수 있다. 이때 모든 정점을 선택하게 되는 시도 횟수의 기댓값을 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.hamayanhamayan.com/entry/2021/03/07/000733&quot;&gt;https://blog.hamayanhamayan.com/entry/2021/03/07/000733&lt;/a&gt;&lt;br&gt;
위 블로그를 참고함.&lt;/p&gt;
&lt;p&gt;일단, &lt;code&gt;성공 확률을 p 라고 할 때, 성공할 때까지 수행 할 때의 시도 횟수는 확률의 역수(1/p)가 된다.&lt;/code&gt; 라는 사실을 알아야 풀 수 있는 문제.&lt;/p&gt;
&lt;p&gt;증명은 에디토리얼을 참고하면 되고 직관적으로 보자면 확률 1/3 짜리가 있다고 할 때 성공의 기댓값은 역수인 3회가 된다.&lt;/p&gt;
&lt;p&gt;이를 이용해보자면 처음은 1개를 골랐으므로 나머지는 n-1개이다. n개 전부를 고르려면 나머지 중에 하나를 골라야 되고 고르는 확률은 n-1 / n 이다. 이에 따른 기댓값은 역수인 n / n-1 이다.&lt;br&gt;
이제 또 다른 나머지에서 골라야 하므로 기댓값은 n / n-2 이 되고 이를 계속해서 더해나가면 된다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;iomanip&gt;
using namespace std;

int main() {
	int n;
	cin &gt;&gt; n;

	long double ans = 0;
	for (int i = 1; i &amp;#x3C; n; i++)
	{
		ans += (long double)n / (n - i);
	}

	cout &amp;#x3C;&amp;#x3C; fixed &amp;#x3C;&amp;#x3C; setprecision(12) &amp;#x3C;&amp;#x3C; ans &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ARC_068_B / ABC_053_D - Card Eater</title><link>https://zeikar.dev/atcoder/posts/67/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/67/</guid><description>수가 적혀진 N개의 카드들이 있다. 카드 중에 3개를 고른 후 가장 작은 수와 가장 큰 수를 빼고 남은 수는 다시 덱에 넣는다. 다른 수의 카드의 개수의 최댓값을 출력하는 문제. 먼저 3개를 고르고 하나를 다시 집어넣는 연산을 잘 살펴보자. 그냥 아무 두 개의 카드를 제거하는 것과 같다는 것을 알 수 있다. 일단, 각 카드가 한 장밖에 없는 경우는 연산을 …</description><pubDate>Tue, 26 Oct 2021 10:00:13 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/arc068/tasks/arc068_b&quot;&gt;https://atcoder.jp/contests/arc068/tasks/arc068_b&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;수가 적혀진 N개의 카드들이 있다.&lt;br&gt;
카드 중에 3개를 고른 후 가장 작은 수와 가장 큰 수를 빼고 남은 수는 다시 덱에 넣는다.&lt;br&gt;
다른 수의 카드의 개수의 최댓값을 출력하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;먼저 3개를 고르고 하나를 다시 집어넣는 연산을 잘 살펴보자.&lt;/p&gt;
&lt;p&gt;그냥 &lt;strong&gt;아무 두 개의 카드를 제거하는 것과 같다&lt;/strong&gt;는 것을 알 수 있다.&lt;br&gt;
일단, 각 카드가 한 장밖에 없는 경우는 연산을 하면 안되고, 두 장 이상 있다면 그 두 장을 다 뽑게 되면 나머지 하나는 다시 덱으로 돌아가기 때문이다.&lt;/p&gt;
&lt;p&gt;각 카드의 수를 전부 센 다음 제거해야 할 개수를 더한 다음 홀수면 카드의 종류의 수 -1, 짝수면 카드의 종류의 수를 출력하면 된다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;map&gt;
using namespace std;

int main() {
	int n;
	cin &gt;&gt; n;

	map&amp;#x3C;int, int&gt; cnt;

	for (int i = 0; i &amp;#x3C; n; i++)
	{
		int a;
		cin &gt;&gt; a;
		cnt[a]++;
	}

	int toRemove = 0;
	for (auto&amp;#x26; i : cnt)
	{
		if (i.second &gt; 1)
		{
			toRemove += i.second - 1;
		}
	}

	if (toRemove % 2 == 0)
	{
		cout &amp;#x3C;&amp;#x3C; cnt.size() &amp;#x3C;&amp;#x3C; endl;
	}
	else
	{
		cout &amp;#x3C;&amp;#x3C; cnt.size() - 1 &amp;#x3C;&amp;#x3C; endl;
	}
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ARC_097_A / ABC_097_C - K-th Substring</title><link>https://zeikar.dev/atcoder/posts/66/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/66/</guid><description>문자열 s 의 모든 부분 문자열 중에서 k 번째로 작은 문자열을 구하는 문제. 일단 힌트는 k가 아주 작다는 것이다. (최대 5) s 의 길이가 최대 5000이므로 s의 모든 부분 문자열을 구하는 것은 n^2이 되고 이론상 시간 안에 들어올 수 있다. 중복을 제거하기 위해 맵을 사용하고, 구한 모든 부분 문자열을 맵에 넣으면 쉽게 풀 수 있다. 처음 제출한…</description><pubDate>Fri, 22 Oct 2021 14:11:59 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/arc097/tasks/arc097_a&quot;&gt;https://atcoder.jp/contests/arc097/tasks/arc097_a&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;문자열 s 의 모든 부분 문자열 중에서 k 번째로 작은 문자열을 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;일단 힌트는 &lt;strong&gt;k가 아주 작다&lt;/strong&gt;는 것이다. (최대 5)&lt;/p&gt;
&lt;p&gt;s 의 길이가 최대 5000이므로 s의 모든 부분 문자열을 구하는 것은 n^2이 되고 이론상 시간 안에 들어올 수 있다.&lt;br&gt;
중복을 제거하기 위해 맵을 사용하고, 구한 &lt;strong&gt;모든 부분 문자열을 맵에 넣으면&lt;/strong&gt; 쉽게 풀 수 있다.&lt;/p&gt;
&lt;p&gt;처음 제출한 답은 그냥 단순히 모든 부분 문자열 중 k 번째를 구했는데 당연히 시간초과. 약간의 최적화를 해서 맵의 크기를 최대 k개 까지만 유지했더니 1초정도로 통과.&lt;/p&gt;
&lt;p&gt;여기서 더 최적화를 할 수 있는데 &lt;strong&gt;k 번째의 부분 문자열의 길이는 최대 k여야만 한다&lt;/strong&gt;는 것을 이용하면 된다.&lt;br&gt;
길이가 k가 넘으면 그보다 작은 부분 문자열(prefix)보다 크게 되기 때문이다. (aaaaaa &gt; aaaaa) 이다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;string&gt;
#include &amp;#x3C;algorithm&gt;
#include &amp;#x3C;map&gt;
using namespace std;

int main() {
	string s;
	int k;

	cin &gt;&gt; s &gt;&gt; k;

	map&amp;#x3C;string, bool&gt; substrs;
	for (int i = 0; i &amp;#x3C; s.length(); i++)
	{
		for (int j = i + 1; j &amp;#x3C;= min(i + k, (int)s.length()); j++)
		{
			substrs[s.substr(i, j - i)] = true;

			if (substrs.size() &gt; k)
			{
				substrs.erase(--substrs.end());
			}
		}
	}

	for (auto const&amp;#x26; str : substrs)
	{
		k--;

		if (k == 0)
		{
			cout &amp;#x3C;&amp;#x3C; str.first &amp;#x3C;&amp;#x3C; endl;
			break;
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_216_E - Amusement Park</title><link>https://zeikar.dev/atcoder/posts/65/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/65/</guid><description>n개의 a 배열이 주어지고 최대 k개를 골라서 최대가 되도록 고르는 문제. 단, 한번 고를 때마다 a 배열의 원소의 값은 1씩 감소한다. 뭔가 이분 탐색으로 가능할 것 같은데 생각보다 쉽지 않았다. 먼저 k개를 넘지 않는 최대 개수를 고르는 지점을 이분 탐색을 이용해서 구할 수 있다. k 개에서 남은 개수만큼 더 고를 수 있는데 이건 따로 한 번 더 탐색해…</description><pubDate>Tue, 19 Oct 2021 13:36:15 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc216/tasks/abc216_e&quot;&gt;https://atcoder.jp/contests/abc216/tasks/abc216_e&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;n개의 a 배열이 주어지고 최대 k개를 골라서 최대가 되도록 고르는 문제.&lt;br&gt;
단, 한번 고를 때마다 a 배열의 원소의 값은 1씩 감소한다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;뭔가 이분 탐색으로 가능할 것 같은데 생각보다 쉽지 않았다.&lt;/p&gt;
&lt;p&gt;먼저 &lt;strong&gt;k개를 넘지 않는 최대 개수를 고르는 지점을 이분 탐색&lt;/strong&gt;을 이용해서 구할 수 있다.&lt;br&gt;
k 개에서 남은 개수만큼 더 고를 수 있는데 이건 따로 한 번 더 탐색해서 구하면 된다.&lt;/p&gt;
&lt;p&gt;예제1로 보면 이분 탐색으로 k개를 넘지 않게 고를 수 있는 값인 100을 구함 (4개 선택 가능)&lt;br&gt;
k 가 5이므로 1개를 더 추가로 고를 수 있는데 이건 아래쪽 for 문으로 cnt를 구해 k 에서 뺀 만큼 99 를 곱해서 더하도록 했다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
using namespace std;

long long a[100000];

int main() {
	long long n, k;
	cin &gt;&gt; n &gt;&gt; k;

	long long high = 0;
	long long low = 0;
	long long ans = 0;

	for (int i = 0; i &amp;#x3C; n; i++)
	{
		cin &gt;&gt; a[i];

		high = max(high, a[i]);
	}

	while (low &amp;#x3C;= high)
	{
		long long mid = (high + low) / 2;
		long long cnt = 0;

		for (int i = 0; i &amp;#x3C; n; i++)
		{
			if (a[i] &amp;#x3C; mid)
			{
				continue;
			}

			long long n = a[i] - mid + 1;
			cnt += n;
		}

		if (cnt &gt; k)
		{
			low = mid + 1;
		}
		else
		{
			high = mid - 1;
		}
	}

	long long cnt = 0;
	for (int i = 0; i &amp;#x3C; n; i++)
	{
		if (a[i] &amp;#x3C; low)
		{
			continue;
		}

		long long n = a[i] - low + 1;
		cnt += n;
		ans += n * (a[i] + low) / 2;
	}
	ans += max((k - cnt) * (low - 1), 0LL);

	cout &amp;#x3C;&amp;#x3C; ans &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>CADDI_2018_B / CADDI_2018B_D - Harlequin</title><link>https://zeikar.dev/atcoder/posts/64/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/64/</guid><description>플레이어와 Lunlun이 번갈아 가며 게임을 한다. 한 턴에 다른 색의 사과만을 먹을 수 있다. 마지막 사과를 먹은 사람이 승자일 때 승자를 구하는 문제. 이런 게임류 문제가 생각보다 까다롭다. 일단, 예제 1번에서 얻을 수 있는 정보는 사과가 한 종류만 남았을 경우 짝수개이면 무조건 진다는 것이다. (하나씩밖에 못 가져가므로) 사과가 두 종류일 때를 시뮬…</description><pubDate>Sat, 16 Oct 2021 07:08:56 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/caddi2018/tasks/caddi2018_b&quot;&gt;https://atcoder.jp/contests/caddi2018/tasks/caddi2018_b&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;플레이어와 Lunlun이 번갈아 가며 게임을 한다.&lt;br&gt;
한 턴에 다른 색의 사과만을 먹을 수 있다.&lt;br&gt;
마지막 사과를 먹은 사람이 승자일 때 승자를 구하는 문제.&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;이런 게임류 문제가 생각보다 까다롭다.&lt;/p&gt;
&lt;p&gt;일단, 예제 1번에서 얻을 수 있는 정보는 사과가 &lt;strong&gt;한 종류만 남았을 경우 짝수개이면 무조건 진다&lt;/strong&gt;는 것이다. (하나씩밖에 못 가져가므로)&lt;br&gt;
사과가 두 종류일 때를 시뮬레이션 해보자.&lt;br&gt;
2, 2인 경우 첫 번째 플레이어가 한 종류만 먹는다고 하면 1,2 이고 두 번째 플레이어가 1개 남은 사과를 먹게 되면 두 번째가 승리한다.&lt;br&gt;
만약 첫 번째 플레이어가 두 종류 다 먹는다면 1,1이 되고 이렇게 해도 두 번째 플레이어가 둘 다 먹게 되어 두 번째가 승리한다.&lt;/p&gt;
&lt;p&gt;짝수개로 일반화도 가능한데, 2n, 2n개인 경우 첫 번째 플레이어가 둘 다 먹든 하나만 먹든 다른 플레이어가 남은 사과의 수를 짝수로 만들어 버릴 수 있으므로 이길 수 없다.&lt;/p&gt;
&lt;p&gt;에디토리얼을 참고하면 모든 사과가 짝수인 상태를 E, 하나라도 홀수가 있다면 O 로 정의한다. 마지막 승리 상태도 E로 볼 수 있다.&lt;br&gt;
처음 시작이 E인 상태일 때 첫 번째 플레이어가 뭘 하든 O 상태로 변화되고 두 번째 플레이어는 다시 E로 전환시킬 수 있다.&lt;br&gt;
처음 시작이 O인 상태일 때는 첫 번째 플레이어가 E로 변환시킬 수 있다.&lt;/p&gt;
&lt;p&gt;즉, 처음 시작이 E인 경우 두 번째 플레이어가 이기고 처음 시작이 O인 경우는 첫 번째 플레이어가 이기게 된다.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;string&gt;
using namespace std;

int a[100000];

int main() {
	int n;
	cin &gt;&gt; n;
	for (int i = 0; i &amp;#x3C; n; i++)
	{
		cin &gt;&gt; a[i];
	}

	string ans = &quot;second&quot;;
	for (int i = 0; i &amp;#x3C; n; i++)
	{
		if (a[i] % 2 != 0)
		{
			ans = &quot;first&quot;;
			break;
		}
	}

	cout &amp;#x3C;&amp;#x3C; ans &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item><item><title>ABC_219_D - Strange Lunchbox</title><link>https://zeikar.dev/atcoder/posts/63/</link><guid isPermaLink="true">https://zeikar.dev/atcoder/posts/63/</guid><description>도시락이 있고 최소 횟수로 x개 이상의 타코야키와 y개 이상의 타이야키를 고르는 문제 딱 보니 dp 냄새가 난다. 범위도 300으로 작으니 해볼만 하다고 생각. 위처럼 dp를 정의하고 다 돌려주면 된다. 단, j, k 값이 계산 중에 300 범위를 넘어갈 수 있는데, 이는 x, j 중에 최솟값으로 처리하면 된다. x 값이 넘는 j의 경우 어차피 상관 없기 …</description><pubDate>Fri, 15 Oct 2021 14:44:54 GMT</pubDate><content:encoded>&lt;h1 id=&quot;user-content-problem-link&quot;&gt;Problem link&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://atcoder.jp/contests/abc219/tasks/abc219_d&quot;&gt;https://atcoder.jp/contests/abc219/tasks/abc219_d&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;user-content-problem-summary&quot;&gt;Problem Summary&lt;/h1&gt;
&lt;p&gt;도시락이 있고 최소 횟수로 x개 이상의 타코야키와 y개 이상의 타이야키를 고르는 문제&lt;/p&gt;
&lt;h1 id=&quot;user-content-solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;딱 보니 dp 냄새가 난다. 범위도 300으로 작으니 해볼만 하다고 생각.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dp[i][j][k] = i 인덱스까지 도시락 중에 j 개의 타코야키, k 개의 타이야키를 고르는 최소 가지 수
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위처럼 dp를 정의하고 다 돌려주면 된다.&lt;/p&gt;
&lt;p&gt;단, j, k 값이 계산 중에 300 범위를 넘어갈 수 있는데, 이는 &lt;strong&gt;x, j 중에 최솟값&lt;/strong&gt;으로 처리하면 된다. x 값이 넘는 j의 경우 어차피 상관 없기 때문.&lt;/p&gt;
&lt;h1 id=&quot;user-content-source-code&quot;&gt;Source Code&lt;/h1&gt;
&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;#include &amp;#x3C;iostream&gt;
#include &amp;#x3C;cstring&gt;
using namespace std;

int n, x, y;
int a[300], b[300];
int dp[301][301][301];

int solve(int idx, int cx, int cy) {
	if (cx &gt;= x &amp;#x26;&amp;#x26; cy &gt;= y)
	{
		return 0;
	}
	if (idx &gt;= n)
	{
		return 987654321;
	}
	if (dp[idx][min(cx, x)][min(cy, y)] != -1)
	{
		return dp[idx][min(cx, x)][min(cy, y)];
	}

	int ret = 987654321;
	// pick
	ret = min(ret, solve(idx + 1, cx + a[idx], cy + b[idx]) + 1);

	// not pick
	ret = min(ret, solve(idx + 1, cx, cy));

	return dp[idx][min(cx, x)][min(cy, y)] = ret;
}

int main() {
	memset(dp, -1, sizeof(dp));

	cin &gt;&gt; n &gt;&gt; x &gt;&gt; y;

	for (int i = 0; i &amp;#x3C; n; i++)
	{
		cin &gt;&gt; a[i] &gt;&gt; b[i];
	}

	int ans = solve(0, 0, 0);

	if (ans == 987654321)
	{
		ans = -1;
	}
	cout &amp;#x3C;&amp;#x3C; ans &amp;#x3C;&amp;#x3C; endl;
}
&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>study</category></item></channel></rss>