문제
- 문제 링크
BOJ 30512 - 조용히 완전히 영원히
길이 $N$의 수열 $A_1, A_2, ... , A_N$이 주어진다.
아래 쿼리가 $Q$개 주어질 때, $Q$개의 쿼리를 순서대로 처리한 후의 수열과 각 쿼리마다 잊힌 원소의 개수를 구해보자.
$L$ $R$ $x$ : 모든 $L ≤ i ≤ R$에 대해 $A_i = min(A_i, x)$를 적용한다.
TL : $1$ sec, ML : $1024$ MB
$1 ≤ N, Q ≤ 100,000$ $0 ≤ A_i, x ≤ 1,000,000$
알고리즘 분류
- 자료 구조 (data_structures)
- 세그먼트 트리 (segtree)
- 느리게 갱신되는 세그먼트 트리 (lazy_propagation)
풀이
구간 업데이트답게 무지성 $lazy$_$propagation$을 구현하자.
구체적으로 각 노드에서 { 현재 값, 마지막으로 영향을 받은 쿼리의 번호 } 를 관리하면 된다.
$Q$번의 업데이트 이후, $propagation$ 연산을 적절히 수행하면 최종 수열의 모습과 $D_1, D_2, ... D_Q$를 구할 수 있다.
각 $D_i$를 구할 땐 최종 수열을 정렬한 뒤 세주는 것이 편하다.
이외에 정말 다양한 풀이들이 존재해 보인다.
$lazy$를 안쓰는 풀이도, 쿼리를 정렬해 $segtree$ 자체를 안쓰는 풀이도 있는 듯 하다.
전체 코드
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #include<bits/stdc++.h> using namespace std; struct { int val = 1e9, idx = 1e9; } lz[1 << 18]; vector <int> D, seg(1 << 18, 1e9); void prop(int n, int s, int e) { auto& [val, idx](lz[n]); if (idx == 1e9) return; if (seg[n] > val) { if (s == e) D[s] = idx; seg[n] = val; } if (s ^ e) { if (lz[n << 1].val > val) lz[n << 1] = { val, idx }; if (lz[n << 1 | 1].val > val) lz[n << 1 | 1] = { val, idx }; } idx = 1e9; } int update(int n, int s, int e, int l, int r, int val, int idx) { prop(n, s, e); if (s > r || e < l) return seg[n]; if (s >= l && e <= r) { lz[n] = { val, idx }; prop(n, s, e); return seg[n]; } int m(s + e >> 1); return seg[n] = min(update(n << 1, s, m, l, r, val, idx), update(n << 1 | 1, m + 1, e, l, r, val, idx)); } int query(int n, int s, int e, int i) { prop(n, s, e); if (s > i || e < i) return 1e9; if (s == e) return seg[n]; int m(s + e >> 1); return min(query(n << 1, s, m, i), query(n << 1 | 1, m + 1, e, i)); } int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n; cin >> n; D.resize(n + 1); for (int i(1); i <= n; i++) { int val; cin >> val; update(1, 1, n, i, i, val, 0); } int q; cin >> q; for (int i(1); i <= q; i++) { int l, r, val; cin >> l >> r >> val; update(1, 1, n, l, r, val, i); } for (int i(1); i <= n; i++) cout << query(1, 1, n, i) << ' '; cout << '\n'; sort(D.begin(), D.end()); for (int cnt{}, i(1), j(1); i <= q; i++) { while (j <= n && D[j] <= i) cnt++, j++; cout << cnt << ' '; } } | cs |
comment
끝
'Problem Solving > Baekjoon Online Judge (Platinum)' 카테고리의 다른 글
백준 30975 - 약간 모자라지만 착한 친구야 (C++) (0) | 2023.12.24 |
---|---|
백준 30943 - Zatopljenje (C++) (1) | 2023.12.11 |
백준 30691 - 슈퍼 트리 뽀개기 (C++) (1) | 2023.11.20 |
백준 30515 - 방형구 탐색 (Hard) (C++) (1) | 2023.11.12 |
백준 20933 - 마스크펑크 2077 (C++) (1) | 2023.11.11 |