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
74
75
76
77
78
79
80
81
82
83
84
  | // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N;
    if (!(cin >> N)) return 0;
    vector<long long> vx(N), vy(N);
    for (int i = 0; i < N; ++i) cin >> vx[i] >> vy[i];
    int K; cin >> K;
    // 수평 구간 추출: yH[i]는 i번째 구간의 높이, xB는 경계(크기 = M+1)
    vector<long long> xB, yH;
    xB.reserve(N/2 + 2);
    yH.reserve(N/2 + 2);
    xB.push_back(vx[0]);
    for (int i = 0; i < N - 1; ++i) {
        if (vy[i] == vy[i + 1]) {
            yH.push_back(vy[i]);
            xB.push_back(vx[i + 1]);
        }
    }
    const int M = (int)yH.size();
    if (M == 0) { cout << 0 << '\n'; return 0; }
    // 최소 카르테시안 트리 구성
    vector<int> leftChild(M, -1), rightChild(M, -1), parent(M, -1);
    vector<int> st; st.reserve(M);
    for (int i = 0; i < M; ++i) {
        int last = -1;
        while (!st.empty() && yH[st.back()] > yH[i]) {
            last = st.back(); st.pop_back();
        }
        if (!st.empty()) {
            parent[i] = st.back();
            rightChild[st.back()] = i;
        }
        if (last != -1) {
            parent[last] = i;
            leftChild[i] = last;
        }
        st.push_back(i);
    }
    int root = -1;
    for (int i = 0; i < M; ++i) if (parent[i] == -1) { root = i; break; }
    // 후위 순회로 구간, 이득, PQ 구성
    vector<int> LB(M), RB(M);
    vector<long long> best(M, 0);
    priority_queue<long long> pq;
    vector<int> stk;
    stk.reserve(2*M + 5);
    stk.push_back(root);
    while (!stk.empty()) {
        int u = stk.back(); stk.pop_back();
        if (u >= 0) {
            stk.push_back(~u);
            if (rightChild[u] != -1) stk.push_back(rightChild[u]);
            if (leftChild[u] != -1) stk.push_back(leftChild[u]);
        } else {
            u = ~u;
            LB[u] = (leftChild[u] != -1 ? LB[leftChild[u]] : u);
            RB[u] = (rightChild[u] != -1 ? RB[rightChild[u]] : u);
            long long parentH = (parent[u] != -1 ? yH[parent[u]] : 0LL);
            long long width = xB[RB[u] + 1] - xB[LB[u]];
            long long rect = width * (yH[u] - parentH);
            long long lval = (leftChild[u] != -1 ? best[leftChild[u]] : 0LL);
            long long rval = (rightChild[u] != -1 ? best[rightChild[u]] : 0LL);
            best[u] = rect + max(lval, rval);
            pq.push(min(lval, rval));
        }
    }
    pq.push(best[root]);
    long long ans = 0;
    for (int i = 0; i < K && !pq.empty(); ++i) {
        ans += pq.top(); pq.pop();
    }
    cout << ans << '\n';
}
  |