문제: icpc.me/12846
알바를 한 기간동안 임금이 가장 적은날을 기준으로 급여를 받을 때 최대 이익을 출력하는 문제이다.
유명한 문제인 히스토그램에서 가장 큰 직사각형과 같은 문제로 해석해도 된다.
세그먼트 트리를 이용하여 최솟값의 위치를 저장한 후 가장 작은 위치를 기준으로 왼쪽 오른쪽을 보며 답을 비교해 나간다.
히스토그램에서 가장 큰 직사각형 문제는 스택으로도 풀 수 있으니 이곳을 참고하도록 하자
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 | #include <cstdio> #include <algorithm> typedef long long ll; using namespace std; int n; int seg[400400]; int arr[100100]; void init(int node, int x, int y) { if (x == y) seg[node] = x; else { int mid = (x + y) >> 1; init(node * 2, x, mid); init(node * 2 + 1, mid + 1, y); if (arr[seg[node * 2]] <= arr[seg[node * 2 + 1]]) seg[node] = seg[node * 2]; else seg[node] = seg[node * 2 + 1]; } } int query(int lo, int hi, int node, int x, int y) { if (y < lo || hi < x) return -1; if (lo <= x&&y <= hi) return seg[node]; int mid = (x + y) >> 1; int q1 = query(lo, hi, node * 2, x, mid); int q2 = query(lo, hi, node * 2 + 1, mid + 1, y); if (q1 == -1)return q2; else if (q2 == -1)return q1; else { if (arr[q1] <= arr[q2]) return q1; else return q2; } } ll sol(int lo, int hi) { int m = query(lo, hi, 1, 0, n - 1); ll res = (ll)(hi - lo + 1)*(ll)arr[m]; if (lo <= m - 1) { ll ans = sol(lo, m - 1); if (res < ans) res = ans; } if (m + 1 <= hi) { ll ans = sol(m + 1, hi); if (res < ans) res = ans; } return res; } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); } init(1, 0, n - 1); printf("%lld\n", sol(0, n - 1)); return 0; } | cs |
'알고리즘 관련 > BOJ' 카테고리의 다른 글
BOJ)10775 공항 (0) | 2017.01.04 |
---|---|
BOJ)12845 모두의 마블 (0) | 2017.01.03 |
BOJ)12844 XOR (0) | 2017.01.03 |
BOJ)10815 숫자 카드 (0) | 2017.01.03 |
BOJ)1733 등번호 (2) | 2017.01.03 |