문제
- 문제 링크
BOJ 12795 - 반평면 땅따먹기
$Li-Chao$ $Tree$
TL : $2$ sec, ML : $128$ MB
$1 ≤ Q ≤ 200,000$ $|a| ≤ 1,000,000$ $|b|, |x| ≤ 1,000,000,000,000$
알고리즘 분류
- 다이나믹 프로그래밍(dp)
- 자료 구조(data structures)
- 볼록 껍질을 이용한 최적화(convex hull trick)
풀이
리차오 트리 그 자체인 문제다.
나는 jhnah917님의 글 에서
리차오 트리를 공부했는데, 되게 참신한 자료 구조라고 생각한다.
노드마다 직선의 방정식을 박을 줄이야..
여튼 $f(x) = ax + b$의 형태에서 $a$와 $b$가 직접적으로 주어진다.
따라서, 동적 노드마다 절반 이상에서 최댓값을 갖는 직선을 취하고 최댓값 쿼리를 날려주면 된다.
전체 코드
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 | #include<bits/stdc++.h> #define ll long long using namespace std; struct L { ll p, q; inline ll f(ll x) { return p * x + q; } }; struct Node { ll l, r, s, e; L ln; }; vector <Node> T; ll q, o, i, j, M(-2e18); void push(L q, ll n) { ll s(T[n].s), e(T[n].e), m((s + e) >> 1); L p = T[n].ln; if (p.f(s) > q.f(s)) swap(p, q); if (p.f(e) <= q.f(e)) { T[n].ln = q; return; } if (p.f(m) < q.f(m)) { T[n].ln = q; if (!~T[n].r) T[n].r = T.size(), T.push_back({ -1, -1, m + 1, e, { 0, M } }); push(p, T[n].r); return; } T[n].ln = p; if (!~T[n].l) T[n].l = T.size(), T.push_back({ -1, -1, s, m, { 0, M } }); push(q, T[n].l); } ll Q(ll x, ll n) { return !~n ? M : max(T[n].ln.f(x), Q(x, ((x << 1) <= T[n].s + T[n].e ? T[n].l : T[n].r))); } int main() { ios_base::sync_with_stdio(0); cin.tie(0); T.push_back({ -1, -1, (ll)-1e12, (ll)1e12, {0, M} }); for (cin >> q; q--;) { cin >> o; if (o & 1) cin >> i >> j, push({ i, j }, 0); else cin >> i, cout << Q(i, 0) << '\n'; } } | cs |
comment
끝
'Problem Solving > Baekjoon Online Judge (Diamond)' 카테고리의 다른 글
백준 15249 - Building Bridges (C++) (0) | 2023.04.26 |
---|---|
백준 14180 - 배열의 특징 (C++) (0) | 2023.04.26 |
백준 4008 - 특공대 (C++) (0) | 2023.04.23 |
백준 18277 - Bliski Brojevi (C++) (0) | 2023.04.23 |
백준 22487 - Do use segment tree (C++) (0) | 2023.04.22 |