문제 링크 : www.acmicpc.net/problem/18251
문제 풀이
이 문제를 보자마자 연관성이 큰 다른문제가 떠오르게 되었다. 문제 링크는 기억이 안나지만 설명을 하자면, 수열이 주어지고 그 수열에서의 부분 최댓값을 구하는 문제이다. 이 문제는 앞에서 부터 계속 더하면서 최댓값을 관리하고 값이 음수가 되었다면 중간에 계속 0으로 초기화 시키는 것을 반복하는 것으로 $O(N)$에 풀 수 있다.
다시 이 문제를 살펴보자. 이 문제와 위에서 설명한 문제의 차이점은 높이가 있다는 것이다. 하지만 전체 노드들의 왼쪽에서 부터 오른쪽으로의 순서는 정해져 있다. 그리고 높이는 lgN이다.
직사각형의 윗변과 아랫변을 정해보자. 이 때 나올 수 있는 경우의 수는 $lg^2N$개이다. 그 두 변 사이에 있는 노드들을 뽑아서 맨 위에 있는 소문제를 풀면 전체 문제를 $O(Nlg^2N)$ 에 해결할 수 있다.
그러고서 틀렸는데, 주어지는 입력 순서가 높이에 따라서 주어진다. 따라서 주어진 입력을 왼쪽부터 순서대로 바꿔주어야 되는데, 이는 중위순회를 해주는 것으로 해결할 수 있다.
코드
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
|
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef pair<ll,ll> pii;
#define ff first
#define ss second
pii arr[2010101];
ll st[2010101];
ll nn;
ll cnt;
ll dd;
void dfs(ll x,ll d){
if(x*2<=nn){
dfs(x*2,d+1);
}
cnt++;
arr[cnt]={d,st[x]};
dd=max(dd,d);
if(x*2+1<=nn){
dfs(x*2+1,d+1);
}
}
int main(){
ll i,j,k,l,m,n;
scanf("%lld",&n);
queue<pii> q;
for(i=1;i<=n;i++)
scanf("%lld",&st[i]);
nn=n;
dfs(1,1);
ll ans=-1e18;
for(i=1;i<=dd;i++)
for(j=i;j<=dd;j++){
ll val=0;
for(k=1;k<=n;k++){
if(arr[k].ff<i||arr[k].ff>j) continue;
val+=arr[k].ss;
ans=max(ans,val);
if(val<0) val=0;
}
}
printf("%lld",ans);
}
|
cs |
'코딩 > 백준 문제 풀이' 카테고리의 다른 글
BOJ 14636 - Money for Nothing (0) | 2021.02.14 |
---|---|
BOJ 13361 - 최고인 대장장이 토르비욘 (3) | 2021.02.13 |
BOJ 14898 - 서로 다른 수와 쿼리 2 (2) | 2020.11.19 |
BOJ 10806 - 공중도시 (0) | 2020.11.09 |
BOJ 8217 - 유성 (0) | 2020.11.01 |