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';
}
|