<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>zse의 블로그</title>
    <link>https://zse05.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 19 Jul 2026 01:09:06 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>zse</managingEditor>
    <item>
      <title>말하는 피아노 만들기</title>
      <link>https://zse05.tistory.com/14</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;동기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;우연히 상용 음성 AI가 흔히 512 포인트 stft로 전처리한다는 이야기를 들었습니다. 또한 보통 학습 및 추론에 사용하는 음성의 샘플링 레이트가 16000Hz라고 합니다. 그렇다면 0~8000Hz상의 257개의 스펙트럼 정보를 이용한다는 것이고, 이는 달리 말하면 이 정도 해상도로도 일상 언어를 이해하는데 무리가 없다는 것입니다. (정확히는 이후에 로그-멜 스펙트로그램이라는 것을 적용한다고 하는데 이는 주파수 bin을 압축 + magnitude에 로그 스케일링이라 다른 정보가 추가되지는 않습니다.) 그런데 피아노 음역대가 27.5 Hz ~ 4186Hz이고, 88개의 반음(A0 ~ C8)으로 구성되어 있으니까, 고주파수 영역을 포기하면 &lt;b&gt;피아노로도 충분히 말하는 듯한 소리를 낼 수 있지 않을까?&lt;/b&gt;라는 의문이 생겼습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 안타깝게도(당연하게도) 이미 있는 아이디어였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 재미있어 보이니 한 번 직접 구현해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;배경지식&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이론을 설명하는 글은 아니니 여기서는 간략하고 좀 덜 엄밀하게 다루겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 적당한 조건을 만족시키는 함수는 서로 다른 주파수를 갖는 삼각함수들을 적절히 더하는 것으로 표현할 수 있습니다. 여기서 어떤 함수를 '주파수를 넣으면 대응하는 주파수 성분을 뱉는 함수'로 바꾸는 것을 푸리에 변환이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 원래 푸리에 변환은 시간에 대한 적분식으로 정의되지만, 적분을 합으로 바꾸고 (유한 개수의 시간 샘플 + 유한한 개수의 주파수)에 대해 수행하면 이산 푸리에 변환이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 푸리에 변환한 함수를 원래 함수로 되돌리는 것은 푸리에 역변환이라고 합니다. 구체적으로 주파수 성분과 해당 주파수의 삼각함수를 곱해서 더하거나 적분하는 행위입니다.&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;- 이산 푸리에 변환을 정의대로 구현하면 점의 개수 N에 대해 점근적으로 $N^2$에 비례하는 연산을 필요로 합니다. FFT는 이를 점근적으로 $N \log N$에 비례하도록 개선한 알고리즘을 의미합니다.&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;- A4(69) = 440Hz를 기준음으로 하여, 반음이 오르거나 내릴 때마다 $2^{ { 1 } \over { 12 } }$를 곱하거나 나누어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 관계식은 다음과 같습니다. (note: 노트 번호(midi), f: 진동수(단위: Hz))&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;$ f = 440 \times 2^{ { \mathrm{note}-69 } \over { 12 } }$&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;$ \mathrm{note} = 69 + 12 \times \log_{2} { { f&amp;nbsp;} \over { 440 } } $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;구현&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 물리적인 피아노로 이것을 구현하기는 너무 어려우니 디지털로 구현해봅시다. 다만 실제 피아노의 물리적인 제약을 가능하면 위반하지 않으면서 구현하려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실제 피아노는 소리를 무한히 크거나 무한히 작게 할 수는 없습니다. 또한 임의 정밀도로 세기를 조절하는 것도 어렵고요. midi에서 velocity를&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;0~127까지&lt;/span&gt; 지원한다고 하니 여기서도 세기를 128 단계로 양자화하도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실제로 건반을 누르면 건반이 원위치로 돌아오기 까지 시간이 조금 걸린다고 합니다. 따라서 한 건반을 아주 짧은 순간에 다시 칠수는 없습니다. 보통 그랜드 피아노가 초당 15회까지 가능하다는 것 같으니 여기서는 조금 보수적으로 초당 10회로 제한해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실제 피아노 소리는 정현파는 아니지만, 디지털로 실제 피아노 소리를 재현하는 것은 어려울 것 같으니 이건 그냥 감수해야 할 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 로직을 작성합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주어진 메시지를 gTTS를 이용하여 음성으로 바꾸고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 음성을 librosa의 stft 함수를 이용하여 분석합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 각 주파수 성분의 세기를 가장 가까운 노트에 합산해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 이를 정규화하여 클리핑을 방지해줍시다.&lt;/p&gt;
&lt;pre id=&quot;code_1779276785654&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import io
import math
import numpy as np
import librosa
from gtts import gTTS
from pydub import AudioSegment

MAX_ACTIVE_KEYS = 40
N_FFT = 2048
ANALYSIS_INTERVAL = 50
PLAYBACK_INTERVAL = 100

MESSAGE = &quot;다람쥐 헌 쳇바퀴에 타고파.&quot;
LANG = &quot;ko&quot;

def text_to_notevol(message, lang):
    tts = gTTS(text=message, lang=lang)

    buf = io.BytesIO()
    tts.write_to_fp(buf)
    buf.seek(0)

    audio = AudioSegment.from_file(buf, format=&quot;mp3&quot;)
    sample = audio.get_array_of_samples()
    y = np.array(sample, dtype=np.float32)/32768

    if audio.channels == 2: y = y.reshape((-1, 2)).mean(axis=1)
    sr = audio.frame_rate

    hop_length = int(sr*ANALYSIS_INTERVAL/1000)
    stft = librosa.stft(y, n_fft=N_FFT, hop_length=hop_length)

    mag = np.abs(stft)
    freq = librosa.fft_frequencies(sr=sr, n_fft=N_FFT)
    notes = np.round(69 + 12*np.log2(freq/440)).astype(int)
    vol = np.zeros((mag.shape[1], 109))
    valid = (21 &amp;lt;= notes) &amp;amp; (notes &amp;lt;= 108)

    for i, note in enumerate(notes[valid]):
        vol[:, note] += mag[valid][i]

    max_val = np.max(np.sum(vol, axis=1))
    if max_val &amp;gt; 0: vol = vol/max_val

    vol = np.clip(np.round(vol*127).astype(int), 0, 127)/127
    return vol

vol = text_to_notevol(MESSAGE, LANG)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ANALYSIS_INTERVAL = 50으로 STFT는 50ms 간격으로 수행합니다. (이보다 간격이 길어지면 소리의 해상도가 너무 낮아질 것이라고 판단했습니다.) 하지만 앞서 언급한 초당 10회 타건이라는 물리적 제약을 지키기 위해 재생은 100ms 단위로 이루어지도록 하였습니다. (PLAYBACK_INTERVAL = 100) 결과적으로 원래 TTS 음성보다 재생 속도는 0.5배로 느려졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N_FFT = 2048인데 주파수 스펙트럼을 촘촘하게 확보하기 위해 512보다 키웠습니다. STFT를 50ms로 다소 느리게 수행했기 때문에 이 정도 크기로 잘 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과로 얻어지는 vol에서 vol[시간][note]은 '그 순간에 해당 note 건반을 얼마나 세게 칠 것인지'를 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 pygame 라이브러리를 이용하여 피아노를 시각화하고, 각 음을 beep음으로 재생시키는 코드를 작성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리에 영상이 안 올라간다는 사실을 몰랐네요...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/ev5jVe/dJMcaffEynG/lGJxjsEnz3KHECjyAv2J9k/Talking%20Piano.mp4?attach=1&amp;amp;knm=tfile.mp4&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;Talking Piano.mp4&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;1.36MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알아듣기 힘들기는 하지만 알고 있으면 들리는 정도는 되는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(메시지는 유명한 팬그램 문장 '다람쥐 헌 쳇바퀴에 타고파.'로 하였습니다.)&lt;/p&gt;</description>
      <category>기타</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/14</guid>
      <comments>https://zse05.tistory.com/14#entry14comment</comments>
      <pubDate>Wed, 20 May 2026 18:42:37 +0900</pubDate>
    </item>
    <item>
      <title>알고리즘 대회 수상 내역 및 기타</title>
      <link>https://zse05.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 백준의 서비스 종료 소식을 듣고서, 여태까지 했던 것들을 조금 기록해봐야겠다는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2026.04.17 기준)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BOJ 맞은 문제: 2495&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;solved.ac rating: &lt;span style=&quot;background-color: #ffffff; color: #f5005a; text-align: start;&quot;&gt;2867 (Ruby III)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;solved.ac arena rating: &lt;span style=&quot;color: #ff143b;&quot;&gt;2432(SSS)&lt;/span&gt; (max. &lt;span style=&quot;color: #ff143b;&quot;&gt;2432(SSS)&lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;codeforces rating: &lt;span style=&quot;color: #ff8c00;&quot;&gt;Master, &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #ff8c00; text-align: start;&quot;&gt;2180&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;(max.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ff8c00;&quot;&gt;international master,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ff8c00;&quot;&gt;2328&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;atcoder rating: &lt;span style=&quot;background-color: #ffffff; color: #c0c000; text-align: start;&quot;&gt;2237&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #aaaaaa;&quot;&gt;―&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;2 Dan (Highest Rating.&amp;nbsp; &lt;span style=&quot;color: #c0c000;&quot;&gt;2241&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #aaaaaa;&quot;&gt;―&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;2 Dan)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기업 대회:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;22 현대모비스 알고리즘 경진대회, 우수상(25등)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;23 현대모비스 알고리즘 경진대회, 우수상(15등)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SCPC 2023 (Samsung Collegiate Programming Cup), 5등상(26등)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LG CPC 2024 (LG Collegiate Programming Contest), 장려상(29등)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;NYPC Code Battle, 특별상(상위 5.85%)&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;b&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;교내 대회:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2022 중앙대학교 CHAC(ChAOS Hello2022 Algorithm Contest), 2등&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2022 중앙대학교 프로그래밍 경진대회(CPC) - Division 1, 1등&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2024 국민대학교 &amp;amp; 중앙대학교 연합 프로그래밍 경진대회, 2등(중앙대 1등)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2025 중앙대학교 프로그래밍 경진대회(CPC), 2등&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2025 Centroid Cup, 3등(중앙대 1등)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙대학교 2025 2학기 코딩경진대회, CAU Coding Master상(총장상, 1등)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Open Contest: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2023 성균관대학교 프로그래밍 경진대회 Open Contest, 우승&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2023 가지컵, 준우승&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2023 서강대학교 청정수컵&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Open Contest, 준우승&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2023 서울대학교 SCSC 프로그래밍 경시대회 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Open Contest, 우승&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;월간향유회 2023. 10., 준우승&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;월간향유회 2023. 11., 준우승&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;2024 상반기 전남대학교 PIMM 알고리즘 파티, 준우승&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;DJMJ 포에버컵, 준우승&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;2025 고려대학교 프로그래밍 경시대회(KCPC) 예비소집 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Open Contest, 준우승&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오픈컨은 원래 백준에서 우승/준우승 횟수도 프로필에 반영해주는데, 어느 순간부터 갱신이 안 되는 게 아쉬워서 넣어봤습니다. 우승 2회, 준우승 7회인데 백준 프로필 상에는 하나도 없네요... &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;카운트 하다보니 생각보다 3등을 한 적이 많다는 것도 알게 되었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ff143b;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;앞으로 이 목록이 늘어나는 일이 있을까요?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>기타</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/13</guid>
      <comments>https://zse05.tistory.com/13#entry13comment</comments>
      <pubDate>Fri, 17 Apr 2026 18:19:03 +0900</pubDate>
    </item>
    <item>
      <title>2025 고려대학교 프로그래밍 경시대회(KCPC) 후기 - 2</title>
      <link>https://zse05.tistory.com/12</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;~ 대회장 입실&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;어쩐지 잠을 네 시간 밖에 못잤습니다. 대충 준비하고 집을 나서서 무인프린트카페에 들러 팀노트를 출력했습니다. 팀노트는 예전에 ICPC 때 만들었던 걸 팀명만 바꿔서 사용했습니다. 사실 팀노트를 사용할 일은 딱히 없을 것 같기는 했습니다. 예비소집 문제들도 어려운 알고리즘을 요구하지 않았고, 솔브드 기준 플래티넘 이하 알고리즘들 중에 알고 있는 것들은 대부분 구현을 암기하고 있기 때문입니다. (그 이상은 어차피 팀노트 봐도 풀 자신이 없었고요...) 그래도 팀노트 챙겨서 손해볼 일은 없을테니 일단 출력했습니다. 대회장까지는 지하철로 갔는데, 노트북이 가벼운 편은 아닌지라 힘들었습니다. 하필이면 이 날따라 지하철에 사람이 매우 많아서 굉장히 피곤하게 이동했습니다. 고려대에 도착하고 보니 시간이 조금 있었는데 대회 직전이라서 뭘 많이 먹기는 좀 부담스럽고, 편의점에서 컵라면으로 점심을 때웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;대회 전&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;대회장 앞에서 등록을 하니 몬스터 한 캔을 같이 나누어 주었습니다. 대회장 앞에 있는 생수 한 병과 젤리 몇 개를 챙겨서 자리에 앉았습니다. 노트북을 켜서 이것저것 확인하고 나니까 시간이 조금 남아서 그냥 쉬었습니다. 도중에 &lt;span style=&quot;color: #ef5369;&quot;&gt;wapas&lt;/span&gt;님을 만나서 간단하게 인사하고 자리에 앉았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;본대회&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;가장 먼저 A번을 확인했습니다. 읽다보니 대충 bfs나 dp 같은 거 열심히 써서 게임 구현하는 문제처럼 보여서, 제일 쉬운 게 이 난이도면 오늘 문제도 엄청 불셋이구나 싶었습니다. 열심히 이런저런 생각을 하고 있었는데 정작 읽고보니 지문의 많은 부분이 풀이에 필요하지 않고, 그냥 맵의 난이도를 결정하는 법만 알면 되는 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:06:30] A번 &lt;span style=&quot;color: #409d00; text-align: start;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왠지 문제 이름들을 보니 H가 풀고 싶어져서 H로 이동하였습니다. 간단하게 쿼리열을 구성하면 되는 문제인데, 문제를 잘못 읽어서 2번 쿼리에 a, b는 주어지는 건 줄 알았습니다. 복잡하고 예외가 많은 문제라고 착각하고 D로 이동했습니다. D는 보니까 C랑 P의 합이 둘 이상이면 무조건 가능하다는 것이 쉽게 보였습니다. 그게 아니면 당연히 안 되겠지 싶어서 바로 제출을 했지만 WA를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;[00:34:24] D번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&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;뭔가 예외가 있다는 건데, 갑자기 엄청 복잡한 문제로 보여서 일단 넘어갔습니다. 삽질을 하는 동안 H가 상당히 많이 풀린 것을 보고 문제에서 뭔가 잘못 읽었다는 것을 깨달았습니다. 다시 읽어보니 간단한 문제라는 걸 깨달을 수 있었고 풀이를 제출해서 AC를 받을 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:49:48] H번 &lt;span style=&quot;color: #409d00; text-align: start;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 F를 봤습니다. 당연하지만 어떤 배열을 정렬하여 얻을 수 있는 배열은 항상 정확하게 하나입니다. 따라서 최댓값이 R, 최솟값이 L인 길이 N 배열이 몇개인지 세면 기댓값을 구할 수 있습니다. 포함 배제 원리를 이용하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(모든 정수 $1 \leq i \leq N$에 대해 $L \leq B_i \leq R$인 길이 N 배열의 수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- (모든 정수 $1 \leq i \leq N$에 대해 $L \leq B_i \leq R-1$인 길이 N 배열의 수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- (모든 정수 $1 \leq i \leq N$에 대해 $L+1 \leq B_i \leq R$인 길이 N 배열의 수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ (모든 정수 $1 \leq i \leq N$에 대해 $L+1 \leq B_i \leq R-1$인 길이 N 배열의 수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로 구할 수 있다는 것을 알았습니다. 이는 $(R-L+1)^N - 2 \cdot (R-L)^N + (R-L-1)^N$를 계산하면 됩니다. 다만 $R = L$때는 (모든 정수 $1 \leq i \leq N$에 대해 $L+1 \leq B_i \leq R-1$인 길이 N 배열의 수)가 0이어야 하는데 예외처리를 안 해줘서 한 번 틀렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:57:14] F번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;br /&gt;[00:58:30] F번 &lt;span style=&quot;color: #409d00; text-align: start;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스코어보드를 보니 이번엔 D가 많이 풀려있었습니다. 또 뭔가 잘못 생각했다는 걸 깨닫고 D로 돌아갔는데 아무리 생각해도 $C+P \geq 2$는 확실한 것 같고 예외는 보이지 않았습니다. K를 이상하게 붙여보다가 아닌 것 같아서 문제를 잘 읽어보니 $K \leq 3$이라는 조건이 눈에 들어왔습니다. 이 조건 하에서는 K가 이상하게 붙어서 답을 만드는 건 불가능 해보였고 $K = 0, 1, 2, 3$에 대해 하나씩 검증해보니 K 하나와 C 하나를 붙여서 조건을 만족시킬 수 있다는 것을 알게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:11:41] D번 &lt;span style=&quot;color: #409d00; text-align: start;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이후 E를 읽어보았습니다. 뭔가 간단하게 바꾸는 방법이 있을까 생각해봤는데 XX를 X 두 개로 읽던 XX 하나로 읽던 결고에 영향이 없다는 것을 알았습니다. 따라서 각 문자가 바뀌는 구간에만 집중하면 될 듯 한데... 그 부분은 딱히 규칙이 안 보여서 자료구조를 사용하는 방법으로 생각을 틀었습니다.&lt;span&gt; 세그먼트 트리에 집어 넣고 &lt;a title=&quot;BOJ 24550번(이 멋진 수열에 쿼리를!)&quot; href=&quot;https://www.acmicpc.net/problem/24550&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BOJ 24550번(이 멋진 수열에 쿼리를!)&lt;/a&gt;처럼 합성해주면 될 것 같다는 생각을 해봤습니다. 근데 일단 각 연산에 대한 연산표가 있어야 하는데 머리가 잘 안 돌아가서 일단 보류했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음으로는 C를 잡았습니다. Catalan Triangle과 누적합으로 답을 구할 수 있다고 생각했는데, 안타깝게도 공식이 기억나지 않았습니다. 팀노트에도 없었고요... 그러면 유도를 해볼 수 있지 않을까 싶었는데 그 전에 시간 복잡도가 안 된다는 것을 깨닫고 보류했습니다. 관찰을 조금 해보니 Catalan Triangle의 점화식이 보였고, 구하고자 하는 값도 $c_{n, k}$꼴의 합이니 비슷한 점화식을 만족시킬 거라는 생각이 들었습니다. 관찰을 더해보니 $3N + 1$꼴일 때 카탈란 수 $C_{N \over 3}$이 하나씩 붙여주면 된다는 것을 알았습니다. 근데 경우의 수가 0인 경우에 0이 아니라 -1로 예외처리 해주라는 지문 내용을 못봐서 한 번 틀렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:52:46] C번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;br /&gt;[01:54:23] C번 &lt;span style=&quot;color: #409d00; text-align: start;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B번과 J번이 풀려있는 것을 보고 우선 J를 잡아봤습니다. 정말 열심히 관찰을 하니 규칙이 보였습니다. C가 들어갈 칸을 일단 먼저 정한 다음에 남은 칸에 K와 P를 채우면 되는데 C가 들어가는 칸을 유효하게 정하려면 다음 두 조건 중에 하나를 만족해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 임의의 행이 인접한 행을 반전시킨 것과 동일한 모양이어야 한다. &lt;br /&gt;2. 임의의 열이 인접한 열을 반전시킨 것과 동일한 모양이어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 행 하나를 임의로 구성하여 1번 규칙에 따라 전체 자리를 구성하는 방법, 열 하나를 임의로 구성하여 2번 규칙에 따라 전체 자리를 구성하는 방법 두 가지를 생각할 수 있습니다. 이 때 체크무늬처럼 구성하는 방법 2가지는 양쪽에 모두 포함되니 포함 배제 원리에 따라 2를 빼주면 됩니다. 그러면 C를 배치하는 방법은 $2^N + 2^M - 2$가지입니다. 이제 K와 P를 남은 공간에 채우는 방법의 수를 곱해주면 되는데 딱 한 칸만 정해주면 나머지는 자연스럽게 결정되는 것처럼 보였습니다. 그래서 답이 $2 \cdot (2^N + 2^M - 2)$라고 생각했지만 예제부터 틀린다는 것을 깨닫고 좀 더 고민해봤습니다. 문제에 있는 그림을 보며 점검을 해보니 C가 들어가는 칸을 줄무늬 모양으로 결정하면 각 줄 별로 독립적으로 K와 P를 채워줄 수 있다는 것을 알 수 있었습니다. 최종적으로 정답은 $2 \cdot (2^N + 2^M - 6) + 2^{\lfloor {N+1 \over 2} \rfloor} + 2^{\lfloor {N \over 2} \rfloor} + 2^{\lfloor {M+1 \over 2} \rfloor} + 2^{\lfloor {M \over 2} \rfloor}$입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[02:45:32] J번 &lt;span style=&quot;color: #409d00; text-align: start;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I번은 너무 어려워보여서 B와 G를 고민해보려고 했습니다. 이때쯤 스코어보드상으로 외부 6등이었기 때문에 한 문제를 더 풀지 못하면 위험하다는 생각을 했습니다. B는 $ab+bc+ca = N$이 되도록 a, b, c를 잘 잡아주면 해결되는데, 문제는 그런 값을 어떻게 찾아야 하는지를 몰랐습니다. 아무리 생각해도 깔끔한 아이디어가 안 떠올라서 적당히 해가 나올 때까지 찾는 방법을 시도해봤습니다. 그런 a, b, c가 항상 있을 것이라는 것과 적당히 순서를 주면 찾는 게 그렇게 오래 걸리지는 않을 거라는 믿음으로 코드를 작성했는데 자꾸 잔실수가 났습니다. (a, b, c의 합을 제대로 체크를 안 한다던지...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[03:55:03] B번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;br /&gt;[03:56:51] B번 &lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;WA&lt;/span&gt; &lt;br /&gt;[03:59:16] B번 &lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;WA&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;그러던 중에 대회가 끝나서 결국 B는 풀지 못했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;대회 후&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;B는 정말 시간이 몇분만 더 있어도 풀었을텐데 너무 아쉬웠습니다. 프리즈 전에 외부 6등이고 그 사이에 아무것도 못했으니 상을 받을 가능성은 거의 없어보였습니다만 열어보기 전에는 모르는 거라고 생각하며 애써 무시했습니다. 아쉬운 마음에 문제지나 좀 더 보다가 짐 정리를 하였습니다. 조금 쉬고 있다보니 오늘도 역시 Kahoot 이벤트가 있었습니다. 빠르게 찍어서 고득점을 노려보았으나 처참한 찍기 실력 (3~4문제 맞은 걸로 기억합니다) 때문에 아무 의미가 없었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(대충 하지만 빨랐죠 짤)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;스코어보드 공개&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1000019309.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1017&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZQWAt/dJMcahQJ7uH/kKIBTOKvZ5fqYURKLWYSkk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZQWAt/dJMcahQJ7uH/kKIBTOKvZ5fqYURKLWYSkk/img.jpg&quot; data-alt=&quot;신기한(...) 닉네임들이 많네요&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZQWAt/dJMcahQJ7uH/kKIBTOKvZ5fqYURKLWYSkk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZQWAt%2FdJMcahQJ7uH%2FkKIBTOKvZ5fqYURKLWYSkk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;1017&quot; data-filename=&quot;1000019309.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1017&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;신기한(...) 닉네임들이 많네요&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이후 스코어보드 오픈이 있었습니다. 위로 한 명이라도 올라가면 순위상에서 쫓겨나는 상황이었지만 거의 기정 사실이었던지라 별로 긴장하며 보지는 않았던 것 같습니다. 예상했던 것처럼 순위가 밀려나서 전체 11등(외부 8등)으로 마무리하였습니다. 특별상도 전부 떨어져서 좀 슬프지만 고수 절취선 위에 있는 걸로 위안 삼아야겠습니다. 전반적으로 패턴 찾기와 조합론이 많았던 것 같은데, 패턴 찾기 쪽이 아무래도 좀 실력이 부족해서인지 실수도 많았고 시간 분배도 많이 말렸다는 생각이 드네요... 그래도 실력에 비해서 결과는 좋게 나온 편이라 이 정도면 만족해도 괜찮을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘 대회 후기/기타 대회</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/12</guid>
      <comments>https://zse05.tistory.com/12#entry12comment</comments>
      <pubDate>Fri, 23 Jan 2026 21:30:53 +0900</pubDate>
    </item>
    <item>
      <title>2025 고려대학교 프로그래밍 경시대회(KCPC) 후기 - 1</title>
      <link>https://zse05.tistory.com/11</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;예비소집&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;예비소집은 현장 참가는 아니고 Open Contest를 통해 참가하게 되었습니다. 예비소집 관련 특별상을 못 받는 건 아쉽지만, 대회 환경에 대해서는 MatKor컵을 참여하면서 어느 정도 파악이 되었기 때문에 크게 문제되는 일은 없을 거라고 생각했습니다. 문제는 어쩌다보니 폰코딩으로 풀게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 A번을 봤는데 예제를 보니 $X_{2N + 1} = (10^N + 1)^2$일 거라고 쉽게 유추해볼 수 있었습니다. 조금 생각해보면 $X_{2N+1}$은 제곱수여야 하고 $(10^N)^2$ 이상이어야 합니다. 그런데 $10^N$은 분명 팰린드롬이 아닙니다. 하지만 $10^N+1$, $(10^N + 1)^2$과 $(10^N + 1)^4$은 모두 팰린드롬이기 때문에 추측이 맞다는 것을 알 수 있습니다. $X_1 = 1$만 예외처리하고 쉽게 AC를 받을 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:04:38] A번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;놀랍게도 오픈콘 기준으로 퍼솔이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음에 B를 봤는데, 매끈매끈하고 푱푱한 바닥에 놓인 세에그트리가 저를 기다리고 있었습니다. 잘은 모르겠지만 케이스워크 또는 계산기하 느낌이 들었습니다. 폰코딩+암산으로 풀기에는 무리가 있을 것 같아 일단 점프했습니다.&lt;/p&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를 봤습니다. 조금 고민해보니 직사각형 내부의 숫자들이 모두 다르려면 직사각형의 넓이가 10을 넘어갈 수는 없다는 것을 알았습니다. 넓이가 10 이하인 직사각형의 수는 27가지입니다. 그러면 왼쪽 위를 고정하고 가능한 직사각형 형태 27가지를 점검하면 될 것 같은데... 약 2억번 정도의 연산이 필요해서 잘못하면 TLE가 날 것 같다는 생각이 들었습니다. 아마 그냥 제출했어도 적당히 돌았을 것 같은데, 폰코딩으로 5중 for문 + 슬라이딩 윈도우를 짠다는 선택을 해버렸고... 어떻게 AC를 받긴 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:40:40] C번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D는 N, M 범위가 작으면 어쩌지 싶었는데 충분히 크게 나왔습니다. 그냥 $X_i \times 1$짜리 2차원 배열에 전부 0 채우면 된다고 생각하고 제출했습니다만...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:44:58] D번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&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;틀릴 포인트가 안 보인다 싶었는데, 지문을 살펴보다가 a, b가 1 이상이라는 조건을 뒤늦게 발견했습니다. a, b를 0에서 10으로 바꿔서 다시 제출하고 AC를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:47:26] D번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;E는 동일한 모양의 위치만 다른 두 직사각형 영역을 잡으면, 상수값 만큼의 차이가 난다는 것을 관찰을 통해 알 수 있습니다. 따라서 모양만 같으면 직사각형 영역들은 전부 조건을 만족하거나 혹은 전부 만족하지 않는다는 것을 알 수 있습니다. 각 테스트 케이스에 대해 27가지 경우를 체크하는 코드를 제출했습니다. 그런데 왜인지 WA를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:54:47] E번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&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;N, M이 크기가 꽤 크다는 사실을 떠올렸고, 변수들을 다 long long으로 바꿨습니다. AC가 나오리라 믿고 제출을 헸으나...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:00:28] E번 &lt;span style=&quot;color: #ee2323;&quot;&gt;TLE&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;하필 TLE가 나왔습니다. 혹시 직접해보지 않아도 a, b값으로 바로 유추할 수 있나 싶었는데 그건 무리일 것 같았습니다. 결국 궁여지책으로 비트마스킹을 사용하기로 했습니다. 첫번째 행의 값만 비트마스킹으로 표현하면 다른 행의 비트마스킹들도 평행이동으로 표현할 수 있으니 조금 더 빠를 것이라고 믿었습니다. 설렁설렁할 줄 알고 폰코딩으로 했는데 이런 짓까지 하게 될 줄은 몰랐습니다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:09:42] E번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맞기는 했습니다만 988ms라는 매우 빠듯한 시간이 나온 걸 보게 되었고, 코드가 심히 비효율적이라는 것을 알게 되었습니다. 하지만 대회 중이니 쿨하게 넘어갑시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 기분 좋게 퍼솔을 하나 더 챙기게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 F를 고민해보았는데, 해싱+투포인터로 풀릴 것 같다는 결론이 나왔습니다. 우선 정방향으로 해싱 + 뒤집어서 읽은 내용으로 해싱을 한 다음, 중앙을 고정한 상태에서 세로는 줄이고 가로는 늘리는 식으로 투포인터를 하면 $O(N^2 M)$에 풀릴 것 같았습니다. 다만 남은 시간을 고려할 때 폰코딩으로는 많이 무리라는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 미뤄두었던 B를 보니 많은 사람들이 푼 상태였습니다. 많은 사람들이 풀었으니 의외로 단순할 수도 있겠다는 생각을 갖고 문제를 봤는데...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀이는 모르겠지만 예제가 너무 $min(a, b)^2$과 $|a - b|$이었습니다. 시간도 별로 없으니 바로 코드 짜서 제출을 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:48:50] B번 &lt;span style=&quot;color: #8a3db6;&quot;&gt;RE&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;...너무 급했는지 입력을 잘못 받았습니다. 그냥 정수 두 개 받는 건데... 고치고 다시 냈는데 이번에는 WA를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:51:16] B번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:57:07] B번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 AC를 받게 되었습니다. 3분 안에 F를 풀 가능성은 정말 없으니 여기서 마무리 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;예비소집 결과&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이상한 실수도 많이 했지만 그런 것치고는 괜찮게 본 것 같습니다. 퍼솔도 두 개나 챙기고 풀어야 하는 문제는 다 푼 것 같았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본대회까지 끝나고 예비소집 스코어보드도 프리즈가 풀렸는데 2등을 하였습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1000019287.jpg&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rfBRY/dJMcacBSGg1/1dOBK8ANiP2PEsrjOQJ4P1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rfBRY/dJMcacBSGg1/1dOBK8ANiP2PEsrjOQJ4P1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rfBRY/dJMcacBSGg1/1dOBK8ANiP2PEsrjOQJ4P1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrfBRY%2FdJMcacBSGg1%2F1dOBK8ANiP2PEsrjOQJ4P1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1012&quot; height=&quot;562&quot; data-filename=&quot;1000019287.jpg&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 노트북으로 참가했으면 오랜만에 오픈콘 1등 가능하지 않았을까 싶긴 한데... 중요한 건 본대회니까요. 일단 배경지식을 강하게 요구하는 문제들은 아니어서 이번에는 느낌이 좀 괜찮았습니다.&lt;/p&gt;</description>
      <category>알고리즘 대회 후기/기타 대회</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/11</guid>
      <comments>https://zse05.tistory.com/11#entry11comment</comments>
      <pubDate>Thu, 22 Jan 2026 12:30:34 +0900</pubDate>
    </item>
    <item>
      <title>Offline Dynamic Connectivity (오프라인 동적 연결성)</title>
      <link>https://zse05.tistory.com/9</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 문제&lt;/b&gt;&lt;/h3&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. 그래프에 간선 (u, v)를 추가하라.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. 그래프에서 간선 (u, v)를 제거하라.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3. 두 정점 u와 v가 같은 연결 요소에 포함되어 있는지 판별하라.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 간선이 추가되기만 한다면, 즉 incremental graph라면 dsu 자료구조를 이용하여 쉽게 풀 수 있습니다. 반대로 간선이 제거되기만 한다면, 즉 decremental graph라면 오프라인 쿼리를 이용하여 역순으로 쿼리를 처리하면 됩니다. 그러면 incremental graph와 동일한 문제가 됩니다. 하지만 추가와 제거가 모두 일어나는 상황에서는 이것만으로는 부족합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 아이디어&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이 문제를 어렵게 하는 것은 기존에 추가한 간선을 다시 제거했을 때 정점들의 연결관계를 알아내기가 쉽지 않다는 것입니다. 그렇다면 왜 이것이 어려울까요? 간선 (u, v)를 추가하고 곧바로 (u, v)를 다시 제거한다고 생각해봅시다. 이는 아주 간단한 상황입니다. 아무것도 일어나지 않은 것과 같은 상황으로, 간선을 추가할 때 생긴 변화를 그저 원상복구 하면 됩니다. 즉 (u, v)를 추가할 때 수정된 변수들을 기억해뒀다가 제거할 때 그 변수들을 되돌려 놓으면 됩니다. 따라서 이 상황에서는 간선의 추가와 제거의 난이도가 동일합니다. 반면에 간선 (u, v)를 추가하고 곧바로 (u, v)를 제거한 것이 아니라 중간에 다른 쿼리들이 끼어있다고 해봅시다. 그렇다면 그 중간의 다른 쿼리들에 따라서 결과가 달라질 수 있습니다. 이는 그래프 전체를 다시 탐색하거나 중간 쿼리들을 모두 살펴보도록 요구하기 때문에 비교적 어려운 문제가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;구체적으로 서로 다른 두 간선이 언제 영향을 주고 받는지 살펴봅시다. lifetime의 관계에 따라 세 가지 케이스로 나눌 수 있습니다.&lt;/p&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;편의상 간선 (a, b)와 (c, d)를 추가하기 전 상태를 (A)라고 하고,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(A)에서 (a, b)만을 추가한 것을 (B),&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(A)에서 (c, d)만을 추가한 것을 (C),&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(A)에서 (a, b), (c, d)를 둘 다 추가한 것을 (D)라고 하겠습니다.&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 data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. disjoint&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;disjoint.png&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;509&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LWFa0/dJMcafrkzQ6/YH30XIeTf8r2OYmGvWHseK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LWFa0/dJMcafrkzQ6/YH30XIeTf8r2OYmGvWHseK/img.png&quot; data-alt=&quot;간선 (a, b)와 (c, d)의 lifetime을 표현한 그래프입니다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LWFa0/dJMcafrkzQ6/YH30XIeTf8r2OYmGvWHseK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLWFa0%2FdJMcafrkzQ6%2FYH30XIeTf8r2OYmGvWHseK%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;984&quot; height=&quot;509&quot; data-filename=&quot;disjoint.png&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;509&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;간선 (a, b)와 (c, d)의 lifetime을 표현한 그래프입니다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(a, b)를 추가하면서 (A) -&amp;gt; (B)로 상태가 변합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(a, b)를 제거하면서 (B) -&amp;gt; (A)로 상태가 변합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(c, d)를 추가하면서 (A) -&amp;gt; (C)로 상태가 변합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(c, d)를 제거하면서 (C) -&amp;gt; (A)로 상태가 변합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉 간선을 제거하는 것이 간선을 추가하는 것의 역과정과 동일합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. inclusion&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;inclusion.png&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;509&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cK2MQi/dJMcaho9b9W/pqb9yTEegMQBuxpw7hKvrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cK2MQi/dJMcaho9b9W/pqb9yTEegMQBuxpw7hKvrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cK2MQi/dJMcaho9b9W/pqb9yTEegMQBuxpw7hKvrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcK2MQi%2FdJMcaho9b9W%2Fpqb9yTEegMQBuxpw7hKvrk%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;984&quot; height=&quot;509&quot; data-filename=&quot;inclusion.png&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;509&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;(a, 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;(c, d)를 추가하면서 (B) -&amp;gt; (D)로 상태가 변합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(c, d)를 제거하면서 (D) -&amp;gt; (B)로 상태가 변합니다. &lt;br /&gt;(a, b)를 제거하면서 (B) -&amp;gt; (A)로 상태가 변합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;마찬가지로 간선을 제거하는 것이 간선을 추가하는 것의 역과정과 동일합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. partial overlap&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;overlap.png&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;509&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d00g4Z/dJMcacBneZ5/3q8ysUQyq6PNiKSTxl2VI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d00g4Z/dJMcacBneZ5/3q8ysUQyq6PNiKSTxl2VI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d00g4Z/dJMcacBneZ5/3q8ysUQyq6PNiKSTxl2VI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd00g4Z%2FdJMcacBneZ5%2F3q8ysUQyq6PNiKSTxl2VI0%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;984&quot; height=&quot;509&quot; data-filename=&quot;overlap.png&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;509&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;(a, 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;(c, d)를 추가하면서 (B) -&amp;gt; (D)로 상태가 변합니다. &lt;br /&gt;(a, b)를 제거하면서 (D) -&amp;gt; (C)로 상태가 변합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(c, d)를 제거하면서 (C) -&amp;gt; (A)로 상태가 변합니다.&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;disjoint, inclusion의 경우에는 간선을 추가할 때 context를 기록해두었다가 제거할 때 그대로 복원하면 되지만 partial overlap에서는 그것이 안됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;따라서 문제를 어렵게 만드는 핵심은 두 간선의 lifetime이 부분적으로 겹칠 때 처리가 번거로워진다는 것입니다. 그렇다면 이런 경우를 어떻게 처리해야 할까요? 우리의 목표는 이런 경우가 생기지 않도록 하는 것입니다. 정확하게는 각 쿼리의 lifetime을 여러 구간으로 나누어서 모든 쿼리가 서로 disjoint 또는 inclusion 관계가 되도록 만들어 줄 겁니다. 그렇게 하면, 간선을 추가하기 직전의 상황을 기억해두기만 하면 간선 제거를 처리할 수 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;마지막으로 이것을 어떻게 자를지 역시 고민해봐야 합니다. 단순하게 모든 쿼리의 lifetime을 1 단위로 다 잘라버리면 원하던대로 disjoint/inclusion중 하나가 됩니다. 하지만 이러면 쿼리의 수 자체가 너무 많아져서 매 쿼리마다 처음부터 다시 그래프를 구성하는 것과 다름이 없어집니다. 따라서 조건을 만족하면서도 쿼리의 수가 너무 많아지지 않도록 영리하게 잘라야 함을 알 수 있습니다. 그리고 각 lifetime을 $O(log\,Q)$개 이내로 잘라서 조건을 만족시킬 수 있다는 게 문제 풀이의 핵심입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 구현&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1761559225222&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#define pii pair&amp;lt;int, int&amp;gt;
struct Intvl { int u, v, s, t; };

int dsu[MAXN];
int rnk[MAXN];
int cnt[MAXQ+1]; //특정 시점에 끝나는 쿼리의 수를 저장하는 배열
stack&amp;lt;pii&amp;gt; st; //쿼리에 대한 히스토리를 저장하기 위한 스택&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Intvl은 간선의 lifetime을 저장하기 위한 구조체입니다. 간선 (u, v)의 lifetime이 [s, t]임을 의미합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;dsu와 rnk는 dsu의 구현을 위해 사용할 변수입니다. cnt와 st는 rollback을 구현하기 위해 사용할 것인데, 모든 lifetime들이 disjoint 또는 inclusion 관계인 상황이기 때문에 스택을 이용하여 간단하게 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그 다음으로 아래의 세가지 기본 함수가 요구됩니다. merge 함수에서 스택에 (dsu값이 변경된 원소, rnk가 변했는지 여부)를 기록하고 있음을 확인하실 수 있습니다. 이미 같은 집합이라 아무것도 변하지 않은 경우에도 편의상 (-1, -1)을 스택에 추가하도록 하였습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1761493978937&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int find(int a) {
    if (a == dsu[a]) return a;
    return find(dsu[a]);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1761494036004&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void merge(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b) {
        st.push({ -1, -1 });
        return;
    }
    if (rnk[a] &amp;lt; rnk[b]) swap(a, b);
    dsu[b] = a;
    st.push({ b, rnk[a] == rnk[b] });
    if (rnk[a] == rnk[b]) rnk[a]++;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1761494114693&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void rollback() {
    auto [n, d] = st.top();
    st.pop();
    if (n == -1) return;
    rnk[dsu[n]] -= d;
    dsu[n] = n;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한편, dsu 최적화를 위해서 path-compression이 아닌 union-by-rank를 사용하였습니다. path-compression의 경우 $amortized \, O(log\,Q)$ 시간 복잡도를 가지지만 개별 쿼리에 대해서는 최악의 경우 $O(Q)$의 복잡도를 가집니다. rollback이 있는 상황에서는 그 부분만을 계속 반복하도록 쿼리열을 구성할 수 있기 때문에 최악 복잡도를 보장할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다음은 각 쿼리의 lifetime을 나눠주는 함수를 구현해야 합니다. 가장 간단하고 많이 사용하는 방법은 세그먼트 트리에 넣어버리는 것입니다. 하지만 과정을 더 명확히 볼 수 있도록 여기서는 명시적으로 세그먼트 트리를 이용하지 않겠습니다. (물론 분할을 위해 사용하는 아래 재귀 함수가 세그먼트 트리에 update하는 과정과 거의 같기는 합니다.)&lt;/p&gt;
&lt;pre id=&quot;code_1761499586607&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void add(vector&amp;lt;Intvl&amp;gt; &amp;amp;intvl, int u, int v, int a, int b, int l, int r) {
    if (r &amp;lt; a || b &amp;lt; l) return;
    if (a &amp;lt;= l &amp;amp;&amp;amp; r &amp;lt;= b) {
        intvl.push_back({ u, v, l, r });
        return;
    }
    int m = (l+r)/2;
    add(intvl, u, v, a, b, l, m);
    add(intvl, u, v, a, b, m+1, r);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 각 쿼리의 lifetime이 $O(log\,Q)$개로 나누어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 구간이 $[a \cdot 2^n, (a+1) \cdot 2^n)$꼴이므로 서로 다른 두 구간이 항상 포함관계거나 disjoint임을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;마지막으로 이렇게 자른 쿼리를 시간순으로 정렬하고 순서대로 처리하면 문제가 해결됩니다. 디테일을 조금 얹으면 시작 시점의 오름차순으로 끝 시점의 내림차순으로 정렬해주면 됩니다. 그래야 쿼리를 처리하는 순서가 자연스럽게 포함관계가 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1761494151623&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int main() {
    /** TODO: 각 간선의 lifetime을 intvl1에 추가하기 **/
    for (auto [a, b, s, t]: intvl1) add(intvl2, a, b, s, t, 0, (1&amp;lt;&amp;lt;17)-1);
    sort(intvl2.begin(), intvl2.end(), [](Intvl a, Intvl b) {
       if (a.s != b.s) return a.s &amp;lt; b.s;
       return a.t &amp;gt; b.t;
    });
    int i = 0;
    for (int q = 0; q &amp;lt; Q; q++) {
        while (cnt[q]--) rollback();
        while (i &amp;lt; intvl2.size() &amp;amp;&amp;amp; intvl2[i].s == q) {
            merge(intvl2[i].u, intvl2[i].v);
            cnt[intvl2[i].t+1]++;
            i++;
        }
        /** TODO: q번째 쿼리 처리하기 **/
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Q개의 쿼리를 나누는 작업은 $O(Q \, log \, Q)$의 시간을 요구합니다.&lt;br /&gt;이렇게 나눠진 $O(Q \, log \, Q)$개의 쿼리를 정렬하기 위해 $O(Q \, log^2 \, Q)$ 복잡도가 요구됩니다.&lt;br /&gt;각각의 쿼리를 처리하기 위해 $O(log \, Q)$ 시간을 필요로 하기 때문에,&amp;nbsp; $O(Q \, log \, Q)$개의 쿼리를 수행하는 것은 $O(Q \, log^2 \, Q)$의 시간을 필요로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론적으로 전체 시간 복잡도는 $O(Q \, log^2 \, Q)$입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 요약&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 각 간선의 lifetime이 partial overlap이 아니면 간선의 제거가 간단해진다. (간선을 추가하기 직전 상황으로 돌리면 된다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 따라서 오프라인 쿼리를 이용하여 lifetime을 전부 구하고, 적당히 나눠서 disjoint 또는 inclusion이 되도록 하면 문제가 간단해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 너무 많이 자르면 복잡도가 커지니 세그먼트 트리 등을 이용하여 $O(log\,Q)$ 이내로 자르면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 전체 시간 복잡도 $O(Q \, log^2 \, Q)$로 문제를 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 마치며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;사실 이러한 테크닉은 동적 연결성 문제에만 제한되는 것은 아닙니다. 어떤 쿼리가 다음 조건을 만족한다면 동일한 테크닉을 사용하여 그 쿼리의 취소를 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 각 쿼리 당 복잡도가 보장될 것 (amortized는 안 됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. update 쿼리의 순서가 질의 쿼리의 결과에 영향을 주지 않을 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1의 경우에는 위에 path-compression과 관련해서 어떤 문제가 생길 수 있는지 이미 확인하였습니다. 2의 경우는 쿼리의 lifetime을 여러 구간으로 나눈 다음에 정렬하기 때문에 그 과정에서 순서가 뒤섞일 수 있기 때문입니다. 동적 연결성 문제에서는 간선 (a, b)를 추가한 다음에 (c, d)를 추가하든 (c, d)를 추가하고 (a, b)를 추가하든 연결성을 판단하는 것에 차이가 없기 때문에 이 조건이 잘 만족되는 것을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/9</guid>
      <comments>https://zse05.tistory.com/9#entry9comment</comments>
      <pubDate>Mon, 27 Oct 2025 02:02:11 +0900</pubDate>
    </item>
    <item>
      <title>중앙대학교 2025-2학기 코딩경진대회 후기</title>
      <link>https://zse05.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;올해 코딩경진대회가 다시 열려서, 저도 처음으로 참가해보게 되었습니다. 대회는 9월 24일 오후 6시부터 9시까지 3시간 진행하였습니다. 온라인 대회라서 집에서 봐도 됐지만 수업이 5시에 끝나기도 하고 세팅하는 것도 시간이 좀 걸릴 것 같아서 학교에서 봤습니다. 다행히도 대회 참가자들을 위해서 학교에서 강의실 몇 곳을 개방해주었네요. 결과가 얼마전에 나왔는데...&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-filename=&quot;1000017401.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/liniC/dJMb9L44mxq/O1CMqKkgkEfgbe7hdKyN51/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/liniC/dJMb9L44mxq/O1CMqKkgkEfgbe7hdKyN51/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/liniC/dJMb9L44mxq/O1CMqKkgkEfgbe7hdKyN51/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FliniC%2FdJMb9L44mxq%2FO1CMqKkgkEfgbe7hdKyN51%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;1018&quot; data-filename=&quot;1000017401.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1018&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;다행히 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;&amp;nbsp;난이도는 조금 쉽게 나온 것 같습니다. 개인적인 의견으로 난이도는 solved.ac 기준으로 &lt;b&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;S2&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;color: #953b34;&quot;&gt;B1&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;G1&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;color: #9feec3;&quot;&gt;P5&lt;/span&gt;&lt;/b&gt; 정도라고 생각이 드네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 풀고 시간 봤을 때 52분이었던 걸로 기억합니다. 3번, 4번에서 실수 한 번씩 해서 조금 걱정했지만 다행히 점수 -&amp;gt; 시간 -&amp;gt; 제출횟수 순으로 순위를 결정하였습니다. ICPC룰처럼 (시간+틀린횟수)로 패널티 줬다면 어쩌면 제가 1등이 아니었을지도 모르겠네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제별 풀이는 간략하게 하면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그: 오프라인 쿼리&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 쿼리들을 순서대로 모두 저장합니다. 1번 쿼리의 유무에 따라서 다음과 같이 풀 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 1번 쿼리(블럭 전부를 한 가지 색으로 다시 칠하는 것)가 없다면 2번 쿼리(블럭 하나를 다시 칠하는 것)는 쿼리 당 O(1) 복잡도로 충분합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 1번 쿼리가 등장한다면, 가장 마지막으로 사용한 1번 쿼리 이전의 쿼리들은 결과에 영향을 줄 수 없습니다. 따라서 가장 마지막으로 등장한 1번 쿼리를 O(N) 복잡도로 처리하고 나머지 쿼리는 O(1) 복잡도로 처리하면 됩니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 다음과 같은 온라인 풀이도 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그: 애드 혹&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바탕색이 있고 그 위에 덧칠을 한 것처럼 생각을 해볼 수 있습니다. 그러면 1번 쿼리는 덧칠한 것을 전부 지우고 &lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;바탕색을 바꾸는 것&lt;/span&gt;으로, 2번 쿼리는 덧칠을 한 번 하는 것으로 생각하면 됩니다. 바탕색은 정수 변수 하나로, 덧칠한 건 c++의 vector와 같은 가변 배열로 관리하여 1번 쿼리에서는 가변 배열을 비우고 2번 쿼리에서는 가변 배열에 원소를 하나 추가하는 식입니다. 배열을 비우는 것은 최악의 경우 O(Q) 복잡도지만, 분할 상환 분석을 이용하여 가변 배열의 원소를 제거하는 비용이 그 원소를 추가할 때 이미 발생한 것으로 간주하면 각 쿼리의 복잡도를 amortized O(1)으로 생각할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그: 애드 혹&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특별히 예외 처리가 없기 때문에 쉬웠던 문제입니다. 어떤 행에서 빈 공간을 무시하고 #O# 순으로 나오면 공이 상자 내부에 있는 것으로 판단할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그: 기하, 정렬, 조합론, 배낭 문제&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 긴 변 하나의 길이가 다른 변들의 길이의 합보다 strict하게 작을 때 다각형을 구성할 수 있고, 그렇지 않으면 구성할 수 없다는 것은 잘 알려진 지식입니다. 즉 찾고자 하는 것은 '크기가 3 이상이고 가장 큰 원소 하나가 다른 원소들의 합보다 strict 하게 작은 부분 집합의 수'입니다. 먼저 모든 원소를 크기 오름차순으로 정렬한 다음에 knapsack table을 관리하면 됩니다. table은 (원소의 수, 원소의 합)을 parameter로 주고 경우의 수를 값으로 저장해줍니다. 그렇게 해서 i번째 원소를 볼 때 테이블에서 [원소의 수&amp;gt;=3][원소의 합&amp;gt;i번째 원소]인 범위를 모두 합해서 답에 더해주면 됩니다. &lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;원소의 수는 3까지만 원소의 합은 개별 원소의 최댓값+1까지만 봐도 충분하므로 테이블 크기를 조절해주면 O(N*max L) 복잡도로 시간 내에 도는 것을 알 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4번&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그: 데이크스트라, 오프라인 쿼리, 이분탐색, 그래프 이론&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dijkstra 알고리즘을 간선의 정방향으로 한 번, 역방향으로 한 번하여 총 두 번 돌려줍니다. S에서 출발하여 어떤 간선 (u, v)를 거쳐서 E로 가는 가장 짧은 경로는 (S에서 u까지 최단 경로)+(u -&amp;gt; v)+(v에서 E까지 최단 경로)입니다. (v에서 E까지 최단 경로의 길이는 역방향 그래프를 통하여 구하면 됩니다.) 그러면 이제 (u, v)를 제거해야하는 가장 작은 x를 알아냈습니다. 이 값들을 정렬한 다음에 이분탐색을 사용하거나 오프라인 쿼리를 사용하면 각 쿼리에 대해 빠르게 답할 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>알고리즘 대회 후기/기타 대회</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/8</guid>
      <comments>https://zse05.tistory.com/8#entry8comment</comments>
      <pubDate>Fri, 24 Oct 2025 23:47:32 +0900</pubDate>
    </item>
    <item>
      <title>2025 Centroid Cup 후기</title>
      <link>https://zse05.tistory.com/7</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;대회 신청&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;대회 신청 공지가 나오고 먼저 각 학교에서 누가 잘하는지, 누가 검수 및 운영으로 빠지는지 그리고 무엇보다 오렌지 유저들이 몇 명 정도 있는지 확인했습니다. 학교마다 오렌지 이상 유저가 3명 정도씩 있는듯 하였고, 운영진/검수진을 제외하고 재학중인 사람만 고려하더라도 오렌지 유저가 4~5명은 참여하겠거니 싶었습니다. 그렇게 생각하니 혼자서 나갔다가는 아무것도 못받고 돌아올 가능성이 있었습니다. (더군다나 14~15문제가 출제된다니 시간 싸움이 꽤 클 것으로 예상이 되고요)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;하지만 아무리 전력분석을 열심히 하더라도 같이 나갈 팀원이 없으면 선택의 여지가 없습니다. 대회 신청이 열리고 열흘 정도 시간이 있었는데 같이 나갈 사람을 찾지 못해서 결국 1인팀으로 신청하게 되었습니다. &quot;상금 혼자서 먹으면 이득!&quot;이라고 정신승리를 해보았지만 과연 상금을 탈 수나 있을까요...&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;&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;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;~ 대회장 입실&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;대회장이 중앙대 310관 726/727호였기 때문에(중앙대 컴공에게는 익숙한 강의실입니다) 비교적 편한 마음으로 대회장으로 향했던 것 같습니다. 대회장 앞에 도착하여 접수를 하니 '핑크빈' or '슬라임'이라는 선택지가 주어졌습니다. 뭔지도 모르고 핑크빈을 고르니 작은 인형을 받을 수 있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1000016975.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byQMzG/btsQTAwJRXK/UOk2OFG7NmCL4GtjoeHDjK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byQMzG/btsQTAwJRXK/UOk2OFG7NmCL4GtjoeHDjK/img.jpg&quot; data-alt=&quot;넥슨 후원 대회에서는 넥슨IP와 관련된 굿즈를 받을 수 있어서 좋습니다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byQMzG/btsQTAwJRXK/UOk2OFG7NmCL4GtjoeHDjK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyQMzG%2FbtsQTAwJRXK%2FUOk2OFG7NmCL4GtjoeHDjK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot; data-filename=&quot;1000016975.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;넥슨 후원 대회에서는 넥슨IP와 관련된 굿즈를 받을 수 있어서 좋습니다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1000016978.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgMVvH/btsQTTpJl0O/UK5HAzkrEpfKqFz8pDk3I0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgMVvH/btsQTTpJl0O/UK5HAzkrEpfKqFz8pDk3I0/img.jpg&quot; data-alt=&quot;중앙대의 마스코트인 푸앙이가 그려진 키링도 같이 받았습니다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgMVvH/btsQTTpJl0O/UK5HAzkrEpfKqFz8pDk3I0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgMVvH%2FbtsQTTpJl0O%2FUK5HAzkrEpfKqFz8pDk3I0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot; data-filename=&quot;1000016978.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;중앙대의 마스코트인 푸앙이가 그려진 키링도 같이 받았습니다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;대회 전&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이후 제 좌석을 확인하며 겸사겸사 다른 팀들 목록도 둘러보고 대회장에 입실하였습니다. 대회장 뒤쪽에는 다과가 준비되어 있었는데, 마침 점심을 먹지 않았던 터라 급하게 집어 먹었습니다. 사소한 걸지도 모르지만 컨디션에 영향을 줄 수도 있다고 생각을 했기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;출제진으로 참가하신 &lt;span style=&quot;color: #ef5369;&quot;&gt;pani&lt;/span&gt;님도 만나뵐 수 있었습니다. (대회 전이었는지 이후였는지 정확히&amp;nbsp;기억이 안 나네요...) 아싸라서 혼자 가만히 있었는데 먼저 말을 걸어주셔서 감사했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;대회 중&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;시작부터 A에 24를 내고 틀렸습니다 (...) &lt;span style=&quot;color: #ee2323;&quot;&gt;틀렸습니다&lt;/span&gt;를 보고도 정신을 못차리고 이유를 고민하다가 숫자를 뒤집어야 한다는 걸 깨달았습니다. 난이도 순 배치가 아니라는 걸 들었기 때문에 A를 풀고서는 적당히 아무 문제로나 넘어갔습니다. D를 잡게 되었는데 예상치도 못하게 꽤 어려워 보였습니다. 이래저래 시간을 무의미하게 끌게 되면서 결국 대회 내내 스코어보드를 쫓아 다니게 되었습니다. 다행히 대부분 어렵지 않게 풀이를 떠올렸으나 필요 이상으로 애를 먹은 문제들이 좀 있었습니다. D는 그냥 사실 2, 3, 4, 6만 완탐 돌리면 된다는 걸 너무 늦게 알았고, G는 보자마자 digit dp를 떠올렸지만 A, B &amp;gt;= N인 경우를 제대로 처리를 안해서 답이 0이어야 하는 경우에 -1를 출력하는 실수가 있었습니다. K는 T순으로 그리디한 걸로 착각했다가 dijkstra로 곧 바꿨습니다. M은 구현 실수가 조금 있었습니다. F는 많아야 성게 4개 정도 연결하면 될 거라고 생각했었지만 증명도 잘 안 됐고, 풀이도 명확하게 떠오르지 않아서 미뤄뒀는데, 위와 같은 실수가 누적되어 풀 시간이 전혀 없었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;대회 후&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;스코어보드는 프리즈 상태였으나 2등은 무리라고 이미 예상은 하고 있었습니다. 프리즈 전에 2등 분에게 이미 밀리고 있었고 G를 1분 남기고 버저비터 하는 바람에 2등 분이 실수를 5~6번 하지 않으면 불가능하다는 결론에 도달했습니다. 할 수 있는 것에 비해 너무 보여준 게 없다는 생각이 들어 많이 아쉬웠습니다. 그래도 자리를 정리하며 마음을 좀 가라앉히려고 노력했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Kahoot!&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;결과가 집계되는 동안에 이벤트성 매치로 Kahoot를 하였습니다. 특별상이 여럿 보이는 것도 그렇고 MatKor컵과 비슷한 운영인 듯 하였습니다. 문제로는 대회와 관련된 TMI들이 주로 나왔습니다. Kahoot는 정답이라고 다 같은 점수를 주는 게 아니라 빨리 맞힌 사람에게 더 높은 점수를 주는데 이 차이가 상당히 큽니다. 그래서 이미 MatKor컵에서 한 번 겪어봤던 저는 질문을 듣고 전혀 유추가 불가능할 거라고 생각한 문제들은 선지를 보지도 않고 그냥 찍었는데, 이 덕을 많이 본 것 같습니다. 게다가 대회 전에 다른 참가자, 출제/운영진을 미리 봐둔 것, 대회 관련해서 주워들었던 것들이 운 좋게도 문제에 나와서 조금 더 유리하게 갈 수 있었습니다. 어떻게 찍기 운까지 조금 따라주었는지 꽤 큰 점수차로 1등을 하게 되었습니다. (저는 18000점대였고 2~5등은 모두 13000점대로 기억합니다.) 상품으로 yes24 디즈니 버클 메쉬 파우치를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;스코어보드 공개&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이후 문제 풀이를 하고, 스코어보드를 공개하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프리즈 이후에 다들 꽤나 풀어서 1,2,3등 자리가 여러 번 바뀌기는 했지만 다들 13솔은 했을 거라고 예상했기 때문에 그 부분은 사실 큰 관심사는 아니었습니다. 결국 패널티 싸움이었는데 역시나 패널티 차이를 따라 잡지 못하고 3등으로 마무리 하였습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1000016998.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vjRCs/btsQVrZ5lrq/aRcNA6XtISRoi8FlifXR11/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vjRCs/btsQVrZ5lrq/aRcNA6XtISRoi8FlifXR11/img.jpg&quot; data-alt=&quot;이제 보니까 패널티 차이 4분 밖에 안 났었네요...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vjRCs/btsQVrZ5lrq/aRcNA6XtISRoi8FlifXR11/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvjRCs%2FbtsQVrZ5lrq%2FaRcNA6XtISRoi8FlifXR11%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;1132&quot; data-filename=&quot;1000016998.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1132&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이제 보니까 패널티 차이 4분 밖에 안 났었네요...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 1등팀이 올솔을 한 거 보고는 감탄을 했습니다. 물론 가장 까다로웠던 F번을 푸셨기 때문에 D는 푸셨을 거라고 생각하고 있었지만요. 국민대에는 저번 (국민대+중앙대) 연합 대회에서도 1등을 뺏겼었는데 이번에 1~2등을 다 뺏겨서 좀 분하네요...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1000016977.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zX6fh/btsQVxFXpk3/aIEONtUtbgCEdB1Bv2wKIk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zX6fh/btsQVxFXpk3/aIEONtUtbgCEdB1Bv2wKIk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zX6fh/btsQVxFXpk3/aIEONtUtbgCEdB1Bv2wKIk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzX6fh%2FbtsQVxFXpk3%2FaIEONtUtbgCEdB1Bv2wKIk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;4032&quot; height=&quot;3024&quot; data-filename=&quot;1000016977.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;여담&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 특별상을 받지 않고 귀가하신 분이 조금 계셔서 Marble Roulette으로 추첨을 하게 되었습니다. 처음 4명 추첨까지는 제 닉네임이 보이지도 않아서 내가 있기는 한 건가 싶었는데, 5번째에서 당첨되어 싸이버거 세트를 받게 되었습니다. 뭔가 이것저것 참 많이 받아가네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 이 날 여의도 한강 공원에서 8시쯤에 불꽃축제가 있었습니다. 노량진에서 조금 보이기는 했지만 힘들기도 하고 운 없으면 인파에 휩쓸릴 것 같아서 그냥 지하철 타고 후다닥 집으로 갔습니다.&lt;/p&gt;</description>
      <category>알고리즘 대회 후기/기타 대회</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/7</guid>
      <comments>https://zse05.tistory.com/7#entry7comment</comments>
      <pubDate>Tue, 30 Sep 2025 04:22:39 +0900</pubDate>
    </item>
    <item>
      <title>SCPC 2024 본선 진출</title>
      <link>https://zse05.tistory.com/6</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1000007614.jpg&quot; data-origin-width=&quot;906&quot; data-origin-height=&quot;395&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9AzPE/btsIXZDhFMT/D0s6ag3p8kkK7axLKkuqp0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9AzPE/btsIXZDhFMT/D0s6ag3p8kkK7axLKkuqp0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9AzPE/btsIXZDhFMT/D0s6ag3p8kkK7axLKkuqp0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9AzPE%2FbtsIXZDhFMT%2FD0s6ag3p8kkK7axLKkuqp0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;906&quot; height=&quot;395&quot; data-filename=&quot;1000007614.jpg&quot; data-origin-width=&quot;906&quot; data-origin-height=&quot;395&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;scpc 올해까지 3번째하면서 느끼는 건, 사람들이 생각하는 것보다 컷이 꽤 낮게 나오는 경우가 많다는 거네요. 대회 직후까지는 1200이면 어련히 본선 가겠거니 싶었는데, 다들 1200+a도 위험하다고 말들이 많았어서 솔직히 나중에는 걱정도 조금 했네요... (사실 1200점 내에서 패널티로 갈렸고 위험하기는 했었네요.) 본선 때는 좀 분발해서 이번에 깔끔하게 2회 수상채우고 scpc 졸업할 수 있으면 좋겠습니다.&lt;/p&gt;</description>
      <category>알고리즘 대회 후기/기타 대회</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/6</guid>
      <comments>https://zse05.tistory.com/6#entry6comment</comments>
      <pubDate>Wed, 7 Aug 2024 16:26:52 +0900</pubDate>
    </item>
    <item>
      <title>2024 SCPC 2차 예선 결과</title>
      <link>https://zse05.tistory.com/5</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1000007564.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kSkpS/btsIP4Tmbk6/ECIFDm5zrk2VcyU5TNEx4K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kSkpS/btsIP4Tmbk6/ECIFDm5zrk2VcyU5TNEx4K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kSkpS/btsIP4Tmbk6/ECIFDm5zrk2VcyU5TNEx4K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkSkpS%2FbtsIP4Tmbk6%2FECIFDm5zrk2VcyU5TNEx4K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;450&quot; data-filename=&quot;1000007564.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1200점 4솔로 마무리 했습니다. elice 본선 일정이랑 겹쳐서 조금 무리해봤는데 결국에는 어느 것 하나 제대로 하지 못한 것 같습니다. 실제로 노트북 잡고 코드 작성한 시간은 2시간도 안 되는 것 같네요... 2차 치고 난이도는 쉬운 편이었던 것 같아요. 그래서인지 딱 1200점은 떨어진다는 의견이 많은데 제 생각에는 가능성이 그렇게 없지는 않은 것 같습니다. 결과 나올 때까지 기다려 봐야겠습니다.&lt;/p&gt;</description>
      <category>알고리즘 대회 후기/기타 대회</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/5</guid>
      <comments>https://zse05.tistory.com/5#entry5comment</comments>
      <pubDate>Mon, 29 Jul 2024 23:03:47 +0900</pubDate>
    </item>
    <item>
      <title>UCPC 2024 예선 후기 (2/2)</title>
      <link>https://zse05.tistory.com/4</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 대회전&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;30분 정도 전에 모여서 가볍게 대화하면서 전략을 정했습니다. 초반에는 2문제씩 잡고 읽다가 적당히 스코어보드 쫓아가기로 했고, 저는 B, C를 잡기로 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 대회&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;대회 전에 의논한 대로 저는 B부터 읽기 시작했습니다. 대충 구성적, 애드혹, 많조분이 떠오르는 문제였는데 어려울 뿐만 아니라 초반에 잡으면 망하는 문제라는 느낌이 들어 15분 정도 고민하다가 버렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러는 동안 팀원이 A를 풀었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:01:32] A번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;B를 포기하고 스코어보드를 보니 C하고 J가 풀려있었습니다. 저는 원래 계획대로 C를 풀었고 D를 풀고 있던 팀원에게 J가 쉬울 것 같으니 D 막혔으면 보라고 했습니다. (지금보니 한 팀이 풀었다고 바로 쫓아간 건, 매우 성급한 판단이었던 것 같아요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C는 보자마자 같은 방향을 보고 있는 미어캣끼리는 키순으로 정렬하는 게 이득일 것 같다는 생각을 했습니다. 하지만 곧 다른 방향을 보고 있는 미어캣에게 영향을 미치기 때문에 그렇지 않다는 것을 깨달았습니다. (애초에 예제만 봐도 아닌게 보이고요...) 조금 더 고민해보니 N^2 솔루션이 떠올라서 바로 구현했습니다. 근데 인덱스 체크를 제대로 안한 곳이 두 곳 있어서 그대로 런타임에러 2회 적립했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러는 동안 다른 팀원이 J를 제출했다가 틀렸습니다. 문제를 잘못 이해했던 듯 싶네요. 패널티에 겁을 먹길래 100번 틀리고 AC 받는 게 못 푸는 것보다 낫다는 점을 상기시켰습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:25:28] J번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:35:17] C번 &lt;span style=&quot;color: #8a3db6;&quot;&gt;RE&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:36:22] C번 &lt;span style=&quot;color: #8a3db6;&quot;&gt;RE&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:40:32] C번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀원들이 각각 E, J에서 묶여있어서 도움을 조금 줬습니다. E는 브루트포스 쪽으로 풀이 작성하면 된다고 알려줬고, J는 반례를 찾아주면서 스택 쪽으로 방향을 잡는 게 좋을 것 같다고 알려줬습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:50:34] E번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[00:51:30] J번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&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;그리고 J에 묶여있는 팀원을 대신해 D번을 봤습니다. 디테일이 귀찮기는 한데 바로 구현하니 어떻게 맞았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:00:35] D번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스코어보드를 보고 G를 잡았는데 각 칸을 2&amp;times;2&amp;times;2로 자르고 union find를 써주면 될 것처럼 보였습니다. 약간의 노가다를 해서 구현했습니다. 그리고 E를 잡았던 팀원이 다행히 금방 구현을 해냈습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:20:39] E번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:28:26] G번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덕분에 순위가 많이 올라갔고, 잘하면 순위 선발로 본선 진출이 가능할 것 같다는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남은 문제는 쉬운 것이 없는 것 같았는데 저는 일단 I를, 다른 팀원은 H를 읽어봤습니다. I를 보고 &quot;쉬운 것 같은데?&quot;라는 느낌이었으나 여기서 구현이 말리면서 디버깅의 늪에 빠지게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;J번을 풀던 팀원은 뭔가 꼬였는지 계속 답을 못내고 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:40:01] J번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:43:06] J번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[01:45:39] J번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[02:00:04] J번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[02:02:19] J번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&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;제가 스택으로 윗면 방향이랑 인덱스를 관리해주면 된다고 살짝 힌트를 줬고 잠시 뒤에 AC를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[02:19:21] J번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 계속 I를 잡고 있었는데, 두 팀원은 같이 H를 보더니 잠시 뒤에 AC를 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[02:23:08] H번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[02:23:59] H번 &lt;span style=&quot;color: #409d00;&quot;&gt;AC&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 I만 풀면 꽤 높은 순위를 받을 수 있을 것 같았지만, 어디가 문제인지 계속 '틀렸습니다'만 나왔네요... 결국 끝까지 못 풀었습니다. 다른 팀원들도 K를 풀려고 했으나 시간이 부족하여 실패했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[02:37:49] I번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[02:50:40] I번 &lt;span style=&quot;color: #ee2323;&quot;&gt;WA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1000007376.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d9Dzl1/btsIyG5EhPJ/DOdsexNSBsP2bqOPkM1fYk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d9Dzl1/btsIyG5EhPJ/DOdsexNSBsP2bqOPkM1fYk/img.jpg&quot; data-alt=&quot;7솔 771 패널티로 마무리 했습니다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d9Dzl1/btsIyG5EhPJ/DOdsexNSBsP2bqOPkM1fYk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd9Dzl1%2FbtsIyG5EhPJ%2FDOdsexNSBsP2bqOPkM1fYk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;585&quot; data-filename=&quot;1000007376.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;7솔 771 패널티로 마무리 했습니다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. 문제 요약&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A. 설명이 따로 필요없을 것 같네요 (&lt;span style=&quot;color: #953b34;&quot;&gt;B5&lt;/span&gt; 예상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B. 어떻게 푸는지 모릅니다. (?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C. 왼쪽을 보는 미어캣 중 키가 가장 큰 몇 명을 뽑아 최대한 왼쪽에 배치하고, 오른쪽을 보는 미어캣 중 키가 가장 큰 몇 명을 뽑아 최대한 오른쪽에 배치합니다. 그리고 나머지는 최대한 얘네의 시야를 가리지 않도록 배치합니다. 왼쪽에서 몇명을 고를지 고정하면 오른쪽은 그리디하게 구할 수 있습니다. 따라서 왼쪽에서 몇명을 뽑을지 0~N까지 탐색해주면 답을 구할 수 있습니다. (&lt;span style=&quot;color: #9feec3;&quot;&gt;P4&lt;/span&gt; 예상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D. A순으로 정렬하면 원본 트리의 inorder와 같아야 합니다. 순서대로 보면서 스택으로 관리하다가 적당히 H가 1 차이 나는 노드들은 부모 자식으로 연결시켜줍니다. 이렇게 생긴 그래프를 dfs해서 조건의 H값을 만족하는 이진 트리인지 확인해주면 됩니다. (&lt;span style=&quot;color: #f3c000;&quot;&gt;G1&lt;/span&gt;-&lt;span style=&quot;color: #9feec3;&quot;&gt;P5&lt;/span&gt; 예상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;E. 과제를 마감시간 순으로 해도 손해볼 것은 없습니다. 따라서 마감시간 순으로 정렬하고 나면 수면을 하는 방법(언제 얼마나 잘 건지)은 10000가지를 넘지 않습니다. 각 케이스를 전부 확인해주면 됩니다. (&lt;span style=&quot;color: #f3c000;&quot;&gt;G4&lt;/span&gt;-&lt;span style=&quot;color: #f3c000;&quot;&gt;G3&lt;/span&gt; 예상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F. 대회 때 안 읽어봐서 모르는데, 뒤에서부터 보면 어떻게 해야하는지 결정될 것 같아보이네요. 근제 솔브수 보니까 이게 아닌가 싶기도 해요. (?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;G. 각 칸을 2&amp;times;2&amp;times;2로 나눠서 생각해보면 원기둥 방향에 따라서 누가 연결되고 누가 나뉘는지 관리할 수 있습니다. connected component 수를 세면 됩니다. (&lt;span style=&quot;color: #f3c000;&quot;&gt;G1&lt;/span&gt; 예상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;H. 제가 안 풀어서 모르는데, 4가지 정도로 케이스 나눠보면 풀릴 것 같아요. (&lt;span style=&quot;color: #f3c000;&quot;&gt;G1&lt;/span&gt; 예상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I. set으로 민들레가 있는 구간들을 관리하면서 L+R 값이 일정값을 넘으면 인접한 구간들을 합치도록 해주면 되는데...어디서 자꾸 틀리는지 모르겠어요 (&lt;span style=&quot;color: #9feec3;&quot;&gt;P1&lt;/span&gt; 예상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;J. 스택에 동전에 대한 정보를 넣습니다. 같은 면의 동전 두 개가 매칭되면 스택에서 제거하는데 이 때 뒷면 두 개가 매칭되면 중간에 있는 앞면 동전을 전부 뒤집었다가 매칭된 두 동전을 합쳐서 다시 뒤집는 과정으로 생각하시면 됩니다. 따라서 답에 (구간 길이/2)+((구간길이-2)/2)를 더하면 됩니다. (&lt;span style=&quot;color: #f3c000;&quot;&gt;G1&lt;/span&gt; 예상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;K. 대회 때 못 봤는데 B가 2 이상 짝수, A가 8 이상 짝수, A가 11 이상 홀수, A = 1, 4, 7인 경우로 나누면 될 것 같습니다. (&lt;span style=&quot;color: #9feec3;&quot;&gt;P4&lt;/span&gt; 예상)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;7. 대회후&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;프리즈 걸린 시점에서 22등이라는 꽤 높은 등수여서 기대 이상으로 매우 잘봤다는 생각을 했습니다. 하지만 프리즈를 풀고나서보니 30분 동안 생각보다 많은 일이 있었는지 35등까지 밀려났습니다. 이것도 나쁘지 않은 결과라고 생각은 들지만... I번을 풀었어야 했다는 아쉬움이 남네요. 제 포지션이 다른 팀원들이 중간 난이도까지 커버해주면 어려운 문제 하나를 풀어내야 하는 자리인데 그 역할을 제대로 못하고 있는 것 같아서 생각이 많아지기도 합니다. 그건 그거고 아마 본선은 갈 가능성이 높지 않을까 싶어요. 본선 규모와 추가 선발 인원에 따라 달라지겠지만 지금으로서는 순위 선발 끝자락 정도는 노려볼 수 있을 것 같아요.&lt;/p&gt;</description>
      <category>알고리즘 대회 후기/기타 대회</category>
      <author>zse</author>
      <guid isPermaLink="true">https://zse05.tistory.com/4</guid>
      <comments>https://zse05.tistory.com/4#entry4comment</comments>
      <pubDate>Sun, 14 Jul 2024 04:09:57 +0900</pubDate>
    </item>
  </channel>
</rss>