πŸ”₯ PS(Problem Solving) πŸ”₯/BOJ

[BOJ] #3653 μ˜ν™” μˆ˜μ§‘

dar0m! 2021. 2. 17. 22:56
μ‹œκ°„ μ œν•œ λ©”λͺ¨λ¦¬ μ œν•œ μ •λ‹΅ λΉ„μœ¨
1 초 256 MB 43.106%
 

3653번: μ˜ν™” μˆ˜μ§‘

각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ— λŒ€ν•΄μ„œ ν•œ 쀄에 m개의 μ •μˆ˜λ₯Ό 좜λ ₯ν•΄μ•Ό ν•œλ‹€. i번째 좜λ ₯ν•˜λŠ” μˆ˜λŠ” i번째둜 μ˜ν™”λ₯Ό λ³Ό λ•Œ κ·Έ μ˜ν™”μ˜ μœ„μ— μžˆμ—ˆλ˜ DVD의 κ°œμˆ˜μ΄λ‹€. μƒκ·Όμ΄λŠ” 맀번 μ˜ν™”λ₯Ό λ³Ό λ•Œλ§ˆλ‹€ λ³Έ μ˜ν™” DVD

www.acmicpc.net

 

문제

μƒκ·Όμ΄λŠ” μ˜ν™” DVD μˆ˜μ§‘κ°€μ΄λ‹€. μƒκ·Όμ΄λŠ” 그의 DVD μ½œλ ‰μ…˜μ„ μŒ“μ•„ λ³΄κ΄€ν•œλ‹€.

보고 싢은 μ˜ν™”κ°€ μžˆμ„ λ•ŒλŠ”, DVD의 μœ„μΉ˜λ₯Ό 찾은 λ‹€μŒ μŒ“μ•„λ†“μ€ μ½œλ ‰μ…˜μ΄ λ¬΄λ„ˆμ§€μ§€ μ•Šκ²Œ μ‘°μ‹¬μŠ€λŸ½κ²Œ DVDλ₯Ό λΊ€λ‹€. μ˜ν™”λ₯Ό λ‹€ λ³Έ μ΄ν›„μ—λŠ” κ°€μž₯ μœ„μ— λ†“λŠ”λ‹€.

μƒκ·Όμ΄λŠ” DVDκ°€ 맀우 많기 λ•Œλ¬Έμ—, μ˜ν™”μ˜ μœ„μΉ˜λ₯Ό μ°ΎλŠ”λ° μ‹œκ°„μ΄ λ„ˆλ¬΄ 였래 κ±Έλ¦°λ‹€. 각 DVD의 μœ„μΉ˜λŠ”, μ°ΎμœΌλ €λŠ” DVD의 μœ„μ— μžˆλŠ” μ˜ν™”μ˜ 개수만 μ•Œλ©΄ μ‰½κ²Œ ꡬ할 수 μžˆλ‹€. 각 μ˜ν™”λŠ” DVD ν‘œμ§€μ— λΆ™μ–΄μžˆλŠ” 숫자둜 μ‰½κ²Œ ꡬ별할 수 μžˆλ‹€.

각 μ˜ν™”μ˜ μœ„μΉ˜λ₯Ό κΈ°λ‘ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€. 상근이가 μ˜ν™”λ₯Ό ν•œ 편 λ³Ό λ•Œλ§ˆλ‹€ κ·Έ DVD의 μœ„μ— λͺ‡ 개의 DVDκ°€ μžˆμ—ˆλŠ”μ§€λ₯Ό ꡬ해야 ν•œλ‹€.

 

ν•΄κ²°

key point, μ„Έκ·Έλ¨ΌνŠΈ 트리, DVD μœ„μΉ˜λŠ” λ°”λ€Œμ–΄λ„, λ²ˆν˜ΈλŠ” λ°”λ€Œμ§€ μ•ŠμŒ
  • λ‹€λ₯Έ μ„Έκ·Έλ¨ΌνŠΈ 트리 λ¬Έμ œμ™€ ν˜•νƒœλŠ” λΉ„μŠ·ν•˜μ§€λ§Œ DVD μœ„μΉ˜κ°€ κ³„μ†ν•΄μ„œ λ°”λ€ŒκΈ° λ•Œλ¬Έμ—, μœ„μΉ˜λ₯Ό 기얡해쀄 배열이 ν•„μš”ν•˜λ‹€ → idx[i]
  • idx[i]λŠ” i번 DVD의 μœ„μΉ˜μ΄λ‹€. μ—„λ°€νžˆ λ§ν•˜λ©΄ μ„Έκ·Έλ¨ΌνŠΈ νŠΈλ¦¬μ—μ„œμ˜ μœ„μΉ˜μ΄λ‹€.
    • idx[i]κ°€ 1이라면, μ„Έκ·Έλ¨ΌνŠΈ νŠΈλ¦¬μ—μ„œλŠ” h번 λ…Έλ“œμ— μžˆλŠ” 것이고, idx[i]κ°€ 6이라면 μ„Έκ·Έλ¨ΌνŠΈ νŠΈλ¦¬μ—μ„œλŠ” h + 6번 λ…Έλ“œμ— μžˆλ‹€.
    • idx[i]값이 1일 λ•Œ 맨 μ•„λž˜ κΉ”λ € μžˆλŠ” DVD이고, top이 맨 μœ„μ— μ‘΄μž¬ν•˜λŠ” DVD이닀.
  • μ„Έκ·Έλ¨ΌνŠΈ 트리의 값을 DVDκ°€ μœ„μΉ˜ν•˜λ©΄ 1, μ—†μœΌλ©΄ 0으둜 두어 ꡬ간 ν•©μœΌλ‘œ i번 DVD μœ„μ— λͺ‡ 개의 DVDκ°€ μžˆλŠ”μ§€ ꡬ할 수 μžˆλ‹€.
    • i번 μ˜ν™”λ₯Ό 보고 μ‹Άλ‹€λ©΄, i번 μ˜ν™”λŠ” idx[i]에 있기 λ•Œλ¬Έμ— κ·Έ μœ„μ— μ‘΄μž¬ν•˜λŠ” DVD의 개수λ₯Ό κ΅¬ν•˜κΈ° μœ„ν•΄μ„œλŠ”
    • idx[i] + 1λΆ€ν„°, topκΉŒμ§€ ꡬ간 ν•©μœΌλ‘œ ꡬ할 수 μžˆλ‹€.

 

μ½”λ“œ

λ©”λͺ¨λ¦¬ μ‹œκ°„
6368 KB 224 ms
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long int ll;
vector<ll>seg;
int idx[200005];
int t, n, m, top;
int h = 1;
void update(int i, int val) {
    i += h - 1;
    seg[i] = val;
    while (i > 1) {
        i /= 2;
        seg[i] = seg[i * 2+ seg[i * 2 + 1];
    }
}
ll query(int l, int r, int num, int nl, int nr) {
    if (l <= nl && nr <= r) return seg[num];
    else if (nl > r || nr < l) return 0;
    int mid = (nl + nr) / 2;
    return query(l, r, num * 2, nl, mid) + query(l, r, num * 2 + 1, mid + 1, nr);
}
int main() {
    scanf("%d"&t);
    while (t--) {
        scanf("%d %d"&n, &m);
        while (h < n + m) h <<= 1//λ†’μ΄κ΅¬ν•˜κΈ° 1 2 4 8
        seg.resize(h * 2);
        for (int i = 0; i < n; i++) {
            update(i + 11);
        }
        for (int i = 1, j = 0; i <= n; i++, j++) {
            idx[i] = n - j;
        }
        top = n;
        for (int i = 0, a; i < m; i++) {
            scanf("%d"&a);
            printf("%lld ", query(idx[a] + 1, top, 11, h));
            update(idx[a], 0);
            idx[a] = ++top;
            update(idx[a], 1);
        }
        puts("");
        seg.clear();
        memset(idx, 0sizeof(idx));
    }
    return 0;
}
cs