[BOJ] #2531 ํšŒ์ „์ดˆ๋ฐฅ (Python, Sliding window, ์‹œ๊ฐ„์ดˆ๊ณผ ํ•ด๊ฒฐ)

    ๋ฐ˜์‘ํ˜•

    ๐ŸŒฑ ๋ฌธ์ œ

    https://www.acmicpc.net/problem/2531

     

    ๐ŸŒฑ ํ’€์ด

    0. ์ž…๋ ฅ๋ฐ›๊ธฐ

    input = sys.stdin.readline
    
    n, d, k, c = map(int, input().split())
    belt = []
    for _ in range(n):
        belt.append(int(input()))

     

    *์ฒ˜์Œ ์ƒ๊ฐํ–ˆ๋˜ ๋ฐฉ๋ฒ• (์‹œ๊ฐ„ ์ดˆ๊ณผ ๋ฐœ์ƒ)

    ์ตœ๋Œ€ ์ ‘์‹œ ์ˆ˜๋Š” 30,000๊ฐœ์ด๋‹ˆ๊นŒ ๋ธŒ๋ฃจํŠธ ํฌ์Šค๋กœ ์ถฉ๋ถ„ํžˆ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ์ŠคํŠธ๋ฅผ ๋Œ๋ฉด์„œ ์ดˆ๋ฐฅ์˜ ์ข…๋ฅ˜๋งŒ ์„ธ์ฃผ๋ฉด ๋˜๋„ค!ํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์งฐ๋Š”๋ฐ ์‹œ๊ฐ„์ดˆ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

    answer = 0
    
    for i in range(n):
        belt.append(belt.popleft())
        answer = max(len(set(list(belt)[:k] + [c])), answer)
    
    print(answer)

    ๊ทธ ์ด์œ ๋Š” ์šฐ์„  for๋ฌธ์ด $O(N)$์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง€๊ณ  $list(belt)[:k]$์—์„œ ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ ํ›„ ์Šฌ๋ผ์ด์‹ฑํ•˜๋Š”๋ฐ์—์„œ $O(k)$ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฆฌ์ŠคํŠธ๋ฅผ set๋กœ ๋ณ€ํ™˜ํ•˜๋Š”๋ฐ์—๋„ $O(k)$์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ€์ง€๋ฏ€๋กœ ์ตœ์ข…์ ์œผ๋กœ for๋ฌธ ์•ˆ์—์„œ $O(k)$ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์œ„์˜ ์ฝ”๋“œ์˜ ์ „์ฒด ์‹œ๊ฐ„๋ณต์žก๋„๋Š” $O(n * k)$๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

     

    1. ํˆฌํฌ์ธํ„ฐ(์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ) ์‚ฌ์šฉํ•˜๊ธฐ

    ์œ„์˜ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํˆฌํฌ์ธํ„ฐ(์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ) ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

    window = defaultdict(int)

    ์šฐ์„  defaultdict๋กœ ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด ๋”•์…”๋„ˆ๋ฆฌ๋Š” ์ดˆ๋ฐฅ์˜ ์ข…๋ฅ˜๋ฅผ ์„ธ๊ธฐ ์œ„ํ•œ ๋”•์…”๋Ÿฌ๋‹ˆ์ž…๋‹ˆ๋‹ค.

     

    2. ์œˆ๋„์šฐ ์ดˆ๊ธฐํ™”

    # Initialize the first window
    for i in range(k):
        window[belt[i]] += 1
    
    # Add the coupon sushi
    window[c] += 1
    answer = len(window)

    ์ฒซ๋ฒˆ์งธ ์œˆ๋„์šฐ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ฒซ๋ฒˆ์งธ ์ดˆ๋ฐฅ๋ถ€ํ„ฐ k๊ฐœ๋ฅผ ์—ฐ์†์œผ๋กœ ๋จน๊ณ  ์ฟ ํฐ ์ดˆ๋ฐฅ๊นŒ์ง€ ๋จน์—ˆ์„ ๋•Œ์˜ ์ดˆ๋ฐฅ์˜ ์ข…๋ฅ˜๋ฅผ ๊ตฌํ•ฉ๋‹ˆ๋‹ค.

     

    3. ํˆฌํฌ์ธํ„ฐ ์˜ฎ๊ธฐ๊ธฐ

    # Slide the window across the belt
    for i in range(1, n + 1):
    
        # Remove the sushi that goes out of the window
        window[belt[i - 1]] -= 1
        if window[belt[i - 1]] == 0:
            del window[belt[i - 1]]
            
        # Add the new sushi that enters the window
        window[belt[(i + k - 1) % n]] += 1
        
        # Update the maximum number of unique sushis
        answer = max(len(window), answer)
    
    print(answer)

    for๋ฌธ์œผ๋กœ belt ๋๊นŒ์ง€ ๋Œ๋ฉด์„œ ์™ผ์ชฝ ์ดˆ๋ฐฅ ํ•˜๋‚˜๋Š” ๋นผ๊ณ  ์˜ค๋ฅธ์ชฝ ์ดˆ๋ฐฅ ํ•˜๋‚˜๋Š” ๋”ํ•ด๊ฐ€๋ฉด์„œ ์ดˆ๋ฐฅ์˜ ์ข…๋ฅ˜๋ฅผ ์„ธ์„œ answer์—๋Š” ์ตœ๋Œ“๊ฐ’์ด ๋“ค์–ด๊ฐ€๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

    ์ด๋ ‡๊ฒŒ ์ฝ”๋“œ๋ฅผ ์งœ๊ฒŒ ๋˜๋ฉด for๋ฌธ ์•ˆ์—์„œ๋Š” ๋ชจ๋“  ์ฝ”๋“œ์˜ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ $O(1)$์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ „์ฒด ์ฝ”๋“œ๋Š” $O(N)$์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

     

    ๐ŸŒฑ ์ •๋‹ต ์ฝ”๋“œ

    # !/usr/bin/env python
    # -*- coding: utf-8 -*-
    # boj 2531 ํšŒ์ „์ดˆ๋ฐฅ
    
    import sys
    from collections import defaultdict
    
    input = sys.stdin.readline
    
    n, d, k, c = map(int, input().split())
    belt = []
    for _ in range(n):
        belt.append(int(input()))
    
    current_window = defaultdict(int)
    
    for i in range(k):
        current_window[belt[i]] += 1
    
    current_window[c] += 1
    answer = len(current_window)
    
    for i in range(1, n):
        current_window[belt[i - 1]] -= 1
        if current_window[belt[i - 1]] == 0:
            del current_window[belt[i - 1]]
        current_window[belt[(i + k - 1) % n]] += 1
        answer = max(answer, len(current_window))
    
    print(answer)
    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€