Algorithm/πŸ‘ 문제

[15961] νšŒμ „μ΄ˆλ°₯

YURIπŸ•πŸ“πŸΆ 2020. 9. 9. 12:41
λ°˜μ‘ν˜•

νšŒμ „μ΄ˆλ°₯ (문제 _ 15961)

νšŒμ „ 초λ°₯ μŒμ‹μ μ—λŠ” νšŒμ „ν•˜λŠ” 벨트 μœ„μ— μ—¬λŸ¬ κ°€μ§€ μ’…λ₯˜μ˜ 초λ°₯이 μ ‘μ‹œμ— 담겨 놓여 있고, μ†λ‹˜μ€ 이 μ€‘μ—μ„œ μžκΈ°κ°€ μ’‹μ•„ν•˜λŠ” 초λ°₯을 κ³¨λΌμ„œ λ¨ΉλŠ”λ‹€. 초λ°₯의 μ’…λ₯˜λ₯Ό 번호둜 ν‘œν˜„ν•  λ•Œ, λ‹€μŒ 그림은 νšŒμ „ 초λ°₯ μŒμ‹μ μ˜ 벨트 μƒνƒœμ˜ 예λ₯Ό 보여주고 μžˆλ‹€. 벨트 μœ„μ—λŠ” 같은 μ’…λ₯˜μ˜ 초λ°₯이 λ‘˜ 이상 μžˆμ„ 수 μžˆλ‹€.

μƒˆλ‘œ 문을 μ—° νšŒμ „ 초λ°₯ μŒμ‹μ μ΄ 뢈경기둜 μ˜μ—…μ΄ μ–΄λ €μ›Œμ„œ, λ‹€μŒκ³Ό 같이 두 κ°€μ§€ 행사λ₯Ό ν†΅ν•΄μ„œ 맀상을 올리고자 ν•œλ‹€.

  1. μ›λž˜ νšŒμ „ 초λ°₯은 μ†λ‹˜μ΄ λ§ˆμŒλŒ€λ‘œ 초λ°₯을 κ³ λ₯΄κ³ , 먹은 초λ°₯만큼 μ‹λŒ€λ₯Ό κ³„μ‚°ν•˜μ§€λ§Œ, 벨트의 μž„μ˜μ˜ ν•œ μœ„μΉ˜λΆ€ν„° k개의 μ ‘μ‹œλ₯Ό μ—°μ†ν•΄μ„œ 먹을 경우 ν• μΈλœ μ •μ•‘ κ°€κ²©μœΌλ‘œ μ œκ³΅ν•œλ‹€.
  2. 각 κ³ κ°μ—κ²Œ 초λ°₯의 μ’…λ₯˜ ν•˜λ‚˜κ°€ 쓰인 쿠폰을 λ°œν–‰ν•˜κ³ , 1번 행사에 μ°Έκ°€ν•  경우 이 쿠폰에 μ ν˜€μ§„ μ’…λ₯˜μ˜ 초λ°₯ ν•˜λ‚˜λ₯Ό μΆ”κ°€λ‘œ 무료둜 μ œκ³΅ν•œλ‹€. λ§Œμ•½ 이 λ²ˆν˜Έμ— μ ν˜€μ§„ 초λ°₯이 ν˜„μž¬ 벨트 μœ„μ— 없을 경우, μš”λ¦¬μ‚¬κ°€ μƒˆλ‘œ λ§Œλ“€μ–΄ μ†λ‹˜μ—κ²Œ μ œκ³΅ν•œλ‹€.

μœ„ 할인 행사에 μ°Έμ—¬ν•˜μ—¬ κ°€λŠ₯ν•œ ν•œ λ‹€μ–‘ν•œ μ’…λ₯˜μ˜ 초λ°₯을 먹으렀고 ν•œλ‹€. μœ„ 그림의 예λ₯Ό κ°€μ§€κ³  μƒκ°ν•΄λ³΄μž. k=4이고, 30번 초λ°₯을 쿠폰으둜 λ°›μ•˜λ‹€κ³  κ°€μ •ν•˜μž. 쿠폰을 κ³ λ €ν•˜μ§€ μ•ŠμœΌλ©΄ 4κ°€μ§€ λ‹€λ₯Έ 초λ°₯을 먹을 수 μžˆλŠ” κ²½μš°λŠ” (9, 7, 30, 2), (30, 2, 7, 9), (2, 7, 9, 25) μ„Έ κ°€μ§€ κ²½μš°κ°€ μžˆλŠ”λ°, 30번 초λ°₯을 μΆ”κ°€λ‘œ 쿠폰으둜 먹을 수 μžˆμœΌλ―€λ‘œ (2, 7, 9, 25)λ₯Ό κ³ λ₯΄λ©΄ 5κ°€μ§€ μ’…λ₯˜μ˜ 초λ°₯을 먹을 수 μžˆλ‹€.

νšŒμ „ 초λ°₯ μŒμ‹μ μ˜ 벨트 μƒνƒœ, 메뉴에 μžˆλŠ” 초λ°₯의 κ°€μ§“μˆ˜, μ—°μ†ν•΄μ„œ λ¨ΉλŠ” μ ‘μ‹œμ˜ 개수, 쿠폰 λ²ˆν˜Έκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, μ†λ‹˜μ΄ 먹을 수 μžˆλŠ” 초λ°₯ κ°€μ§“μˆ˜μ˜ μ΅œλŒ“κ°’μ„ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

μž…λ ₯
첫 번째 μ€„μ—λŠ” νšŒμ „ 초λ°₯ λ²¨νŠΈμ— 놓인 μ ‘μ‹œμ˜ 수 N, 초λ°₯의 κ°€μ§“μˆ˜ d, μ—°μ†ν•΄μ„œ λ¨ΉλŠ” μ ‘μ‹œμ˜ 수 k, 쿠폰 번호 cκ°€ 각각 ν•˜λ‚˜μ˜ 빈 칸을 사이에 두고 μ£Όμ–΄μ§„λ‹€. 단, 2 ≤ N ≤ 3,000,000, 2 ≤ d ≤ 3,000, 2 ≤ k ≤ 3,000 (k ≤ N), 1 ≤ c ≤ d이닀.

두 번째 쀄뢀터 N개의 μ€„μ—λŠ” 벨트의 ν•œ μœ„μΉ˜λΆ€ν„° μ‹œμž‘ν•˜μ—¬ νšŒμ „ λ°©ν–₯을 λ”°λΌκ°ˆ λ•Œ 초λ°₯의 μ’…λ₯˜λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 1 이상 d μ΄ν•˜μ˜ μ •μˆ˜κ°€ 각 μ€„λ§ˆλ‹€ ν•˜λ‚˜μ”© μ£Όμ–΄μ§„λ‹€.

좜λ ₯
μ£Όμ–΄μ§„ νšŒμ „ 초λ°₯ λ²¨νŠΈμ—μ„œ 먹을 수 μžˆλŠ” 초λ°₯의 κ°€μ§“μˆ˜μ˜ μ΅œλŒ“κ°’μ„ ν•˜λ‚˜μ˜ μ •μˆ˜λ‘œ 좜λ ₯ν•œλ‹€.

예제

8 30 4 30
7
9
7
30
2
7
9
25

< answer >
5

풀이

무쑰건 k개λ₯Ό μ—°μ†ν•΄μ„œ λ¨Ήμ–΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— μ²˜μŒλΆ€ν„° k개λ₯Ό μ—°μ†ν•΄μ„œ 먹어보고, ν•œ μΉΈ μ΄λ™ν•΄μ„œ μ—°μ†ν•΄μ„œ 먹어보고, ν•œ μΉΈ 또 μ΄λ™ν•˜κ³  μ΄λŸ°μ‹μœΌλ‘œ μ§„ν–‰ν•˜λ©΄ λœλ‹€.

μ΄λ•Œ μ΅œλŒ€λ‘œ 먹을 수 μžˆλŠ” 초λ°₯의 μ’…λ₯˜λ₯Ό 계산해야 ν•˜κΈ° λ•Œλ¬Έμ— μ§€κΈˆκΉŒμ§€ 먹은 초λ°₯의 μ’…λ₯˜μ™€ λͺ‡κ°œμ”© λ¨Ήμ—ˆλŠ”μ§€ μ €μž₯ν•˜λŠ” 과정이 ν•„μš”ν•˜λ‹€.

selected[] - ν•΄λ‹Ή μ’…λ₯˜μ˜ 초λ°₯을 먹은 개수
cnt - 먹은 초λ°₯의 μ’…λ₯˜

 

예λ₯Ό λ“€μ–΄ 1 4 3 4 4 λ₯Ό μ—°μ†ν•΄μ„œ λ¨Ήμ—ˆμ„ 경우

selected[1] = 1

selected[2] = 0

selected[3] = 1

selected[4] = 3

cnt =3

 

μ²˜μŒλΆ€ν„° k개λ₯Ό 연속해 초λ°₯을 λ¨ΉμœΌλ©΄μ„œ selected와 cnt 값을 μ§€μ •ν•΄ μ€€ λ‹€μŒ ν•œ μΉΈμ”© 초λ°₯을 λΉΌκ³  μΆ”κ°€ν•˜λŠ” 과정을 거쳐쀀닀.

0번째 초λ°₯λΆ€ν„° 5λ²ˆμ§ΈκΉŒμ§€ λ¨Ήμ—ˆλ‹€λ©΄, 1λ²ˆμ§ΈλΆ€ν„° 6λ²ˆμ§ΈκΉŒμ§€ λ¨ΉλŠ”λ‹€κ³  μƒκ°ν•˜λ©΄ λœλ‹€.

μ΄λ•Œ 2,3,4,5의 초λ°₯을 λ¨ΉλŠ” 건 λ™μΌν•˜κΈ° λ•Œλ¬Έμ— 0번째 초λ°₯을 selected와 cntμ—μ„œ λΉΌμ£Όκ³  6번째 초λ°₯을 μΆ”κ°€ν•΄ μ£Όλ©΄ λœλ‹€.

μ΄λŸ°μ‹μœΌλ‘œ n번째 초λ°₯λΆ€ν„° k번 μ—°μ†ν•΄μ„œ λ¨ΉλŠ” κ²½μš°κΉŒμ§€ λ°˜λ³΅ν•΄μ£Όκ³  μ΅œλŒ€λ‘œ 먹을 수 μžˆλŠ” 초λ°₯의 μ’…λ₯˜μ˜ 개수λ₯Ό 좜λ ₯ν•œλ‹€

μ½”λ“œ

    // μ²˜μŒλΆ€ν„° kκ°œκΉŒμ§€ μ—°μ†μœΌλ‘œ 먹음
    selected[sushi[0]] = 1;
    int cnt = 1; // 초λ°₯ μ’…λ₯˜
    int end = 0; // λ§ˆμ§€λ§‰μœΌλ‘œ 먹은 초λ°₯ 인덱슀 μ €μž₯ν•˜κΈ° μœ„ν•œ λ³€μˆ˜

    for (int next = 1, tmp = 1; tmp < k; next++, tmp++) {
        if (next == n) next = 0; // λ‹€μ‹œ 처음으둜 λŒμ•„κ°
        if (selected[sushi[next]++] == 0) // 처음으둜 λ¨ΉλŠ” 초λ°₯이라면
            cnt++;
        end = next; // λ§ˆμ§€λ§‰ 인덱슀 μ €μž₯
    }
    // μ„œλΉ„μŠ€ 초λ°₯ λ¨ΉκΈ°
    if(selected[c]++ == 0) cnt++;    
    ans = cnt; // ν˜„μž¬κΉŒμ§€ 먹은 초λ°₯ 개수

    for (int i = 1; i < n; i++) {
        if(--selected[sushi[i-1]]==0) cnt--; // i-1번째 초λ°₯은 λ¨Ήμ§€ μ•ŠμŒ
        if(++end == n) end= 0; // νšŒμ „μ΄ˆλ°₯ μˆœν™˜
        if(selected[sushi[end]]++ == 0) { // 처음 λ¨ΉλŠ” 초λ°₯이라면
            cnt++;
        }
        if(cnt > ans) ans = cnt; // 초λ°₯ μ’…λ₯˜ 개수 μ €μž₯
    }
λ°˜μ‘ν˜•