알고리즘 문제 풀이
백준 2104, 6549 C++ 풀이
mines213
2024. 8. 23. 22:16
https://www.acmicpc.net/problem/2104
https://www.acmicpc.net/problem/6549
2104 부분배열 고르기
구간의 최솟값*구간합을 최대로 만들어야 한다.
A[i]를 전체 구간의 최솟값이라고 했을 때,
A[i]를 포함하여 최대값을 만들려면 A[i]*전체구간합이 최대값인 것은 자명하다.
다른 최대값을 확인하려면 A[i]을 제외한 다른 구간을 봐야만 한다.
(~A[i-1]) , (A[i+1]~) 이 두 구간으로 자를 수 있다.
이를 반복하면 최대값을 얻을 수 있다.
#include <bits/stdc++.h>
#define ll long long
#define fastio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
ll ans = 0;
ll arr[1000001];
//비재귀 세그먼트 트리
int tree_size, base;
vector<pair<ll,ll> > seg_tree;
void init(int size) {
tree_size = size;
seg_tree.resize(tree_size << 2, {0x7f7f7f7f, 0});
for (base = 1; base < tree_size; base <<= 1);
}
void update(int i, ll x) {
i += base;
seg_tree[i] = {x, i - base};
for (i = i >> 1; i > 0; i = i >> 1)
seg_tree[i] = min(seg_tree[i << 1], seg_tree[i << 1 | 1]);
}
pair<ll,ll> query(int p, int q) {
// [p,q]
p += base, q += base;
pair<ll,ll> ret = {0x7f7f7f7f, 0};
while (p < q) {
if (p & 1) ret = min(ret, seg_tree[p++]);
if (~q & 1) ret = min(ret, seg_tree[q--]);
p = p >> 1, q = q >> 1;
}
if (p == q) ret = min(ret, seg_tree[p]);
return ret;
}
void f(int s, int e) {
if (s >= e)
return;
ll MIN;
int idx;
tie(MIN, idx) = query(s, e);
ans = max(ans, MIN * (arr[e + 1] - arr[s]));
f(s, idx - 1);
f(idx + 1, e);
}
int main() {
fastio;
int N, tmp;
cin >> N;
init(N);
for (int i = 0; i < N; i++) {
cin >> tmp;
arr[i + 1] = arr[i] + tmp;
ans = max(ans, 1ll * tmp * tmp);
update(i, tmp);
}
f(0, N - 1);
cout << ans;
return 0;
}
6549 히스토그램에서 가장 큰 직사각형
직사각형의 넓이는 가로*높이이다.
구간의 길이를 가로라고 했을 때, 높이는 구간의 최솟값이다.
A[i]를 전체 구간의 가장 작은 높이라고 했을 때,
A[i]를 포함하여 최대값을 만들려면 A[i]*전체 가로 길이가 최대값인 것은 자명하다.
다른 최대값을 확인하려면 A[i]을 제외한 다른 구간을 봐야만 한다.
(~A[i-1]) , (A[i+1]~) 이 두 구간으로 자를 수 있다.
이를 반복하면 최대값을 얻을 수 있다.
#include <bits/stdc++.h>
#define ll long long
#define fastio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
#define X first
#define Y second
ll ans;
//비재귀 세그먼트 트리
int n, base;
vector<pair<int, int> > tree;
void init(int size) {
n = size;
tree.resize(n << 2, {0x3f3f3f3f, -1});
for (base = 1; base < n; base <<= 1);
}
void update(int i, int x) {
i += base;
tree[i].X = x;
tree[i].Y = i - base;
for (i = i >> 1; i > 0; i = i >> 1)
tree[i] = min(tree[i << 1], tree[i << 1 | 1]);
}
pair<int, int> query(int p, int q) {
p += base, q += base;
pair<int, int> ret = {0x7f7f7f7f, -1};
while (p < q) {
if (p & 1) ret = min(ret, tree[p++]);
if (~q & 1) ret = min(ret, tree[q--]);
p = p >> 1, q = q >> 1;
}
if (p == q) ret = min(ret, tree[p]);
return ret;
}
void f(int s, int e) {
int MIN, mid;
if (s >= e)
return;
tie(MIN, mid) = query(s, e);
ans = max(ans, 1ll * MIN * (e - s + 1));
f(s, mid - 1);
f(mid + 1, e);
}
int main() {
fastio;
int N, tmp;
cin >> N;
while (N != 0) {
ans = 0;
init(N);
for (int i = 0; i < N; i++) {
cin >> tmp;
ans = max(ans, 1ll * tmp);
update(i, tmp);
}
f(0, N - 1);
cout << ans << "\n";
cin >> N;
}
return 0;
}