반응형
문제 요약
n개의 빌딩의 높이 $h_i$가 주어진다.
이 때, $(h_i+h_j)(j-i), (i \le j)$의 최댓값을 구해야 한다.
n은 최대 100만이고, 주어지는 높이의 최대도 100만이다.
풀이
두 개의 점의 집합을 정의하자.
$$
P={(i,-h_i)}, Q={(i,h_i)}
$$
그러면 이제 이 문제는 집합 $P$의 점을 왼쪽 아래로 하고, 집합 $Q$의 점을 오른쪽 위로 하는 직사각형 중에서 최대 넓이를 가지는 직사각형의 넓이를 구하는 문제와 동치가 된다.
그러면 이 문제는 백준 14636번 Money for Nothing과 동일한 문제가 된다. 이제 문제를 풀 수 있다. 풀이 링크
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int N, M;
vector<pair<ll, ll>> P, C;
vector<pair<ll, ll>> L, U;
ll dp[1000005];
ll mx;
void solve(int s, int e, int optl, int optr) {
if (s > e) return;
int mid = (s + e) >> 1;
int opt = optl;
ll& ans = dp[mid];
ans = -2e18;
for (int i = optl; i <= optr; ++i) {
ll dt = U[i].second - L[mid].second;
ll dp = U[i].first - L[mid].first;
if (dt >= 0 || dp >= 0) {
ll val = dt * dp;
if (ans <= val) {
ans = val; opt = i;
}
}
}
solve(s, mid - 1, optl, opt);
solve(mid + 1, e, opt, optr);
mx = max(mx, ans);
}
int main() {
cin.tie(nullptr); ios::sync_with_stdio(false);
cin >> N;
for(int i=0;i<N;++i) {
ll x; cin >> x;
P.push_back({i,x});
C.push_back({i,-x});
}
sort(P.begin(), P.end());
sort(C.begin(), C.end());
for (int i = 0; i < N; ++i) {
if(L.empty() || L.back().second > C[i].second) L.push_back(C[i]);
}
for (int i = 0; i < N; ++i) {
while (!U.empty() && U.back().second <= P[i].second) U.pop_back();
U.push_back(P[i]);
}
// memset(dp, -1, sizeof(dp));
solve(0, L.size() - 1, 0, U.size() - 1);
cout << max(0LL,mx) << '\n';
return 0;
}
반응형
'Problem Solving > 문제풀이' 카테고리의 다른 글
백준 13058번 Jewel Thief (0) | 2021.02.16 |
---|---|
백준 14179번 크리스마스 이브 (0) | 2021.02.16 |
백준 16138번 수강신청 (2) | 2021.02.16 |
백준 12766번 지사 배정 (0) | 2021.02.16 |
백준 11001번 김치 (0) | 2021.02.16 |