일직선으로 다양한 높이의 건물이 총 개가 존재한다. 각 건물 옥상에서 양 옆에 존재하는 건물의 옆을 몇 개 볼 수 있는지 궁금해졌다.
번째 건물 기준으로 , , ..., 번째 건물은 왼쪽에, , , ..., 번째 건물은 오른쪽에 있다. 각 건물 사이의 거리는 다 동일하다.
현재 있는 건물의 높이가 이라고 가정하면 높이가 보다 큰 곳의 건물만 볼 수 있다.
바라보는 방향으로 높이가 인 건물 뒤에 높이가 이하인 건물이 있다면 가려져서 보이지 않는다.
| 번호 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| 높이 | 3 | 7 | 1 | 6 | 3 | 5 | 1 | 7 |
| 보이는 건물 번호 | 2 | x | 2, 4, 8 | 2, 8 | 2,4,6,8 | 2,4,8 | 2,4,6,8 | x |
각 건물에서 볼 수 있는 건물들이 어떤것이 있는지 구해보자.
첫번째 줄에 건물의 개수 이 주어진다.
두번째 줄에는 개의 건물 높이가 공백으로 구분되어 주어진다..
번째 건물에서 볼 수 있는 건물의 개수를 출력한다.
만약 볼 수 있는 건물의 개수가 1개 이상이라면 번째 건물에서 거리가 가장 가까운 건물의 번호 중 작은 번호로 출력한다.
8
3 7 1 6 3 5 1 7
1 2
0
3 2
2 2
4 4
3 4
4 6
0
import sys
input = sys.stdin.readline
n = int(input().rstrip())
l = list(map(int,input().rstrip().split()))
stack = []
cnt = [0]*(n+1)
near = [[int(1e9),int(1e9)] for _ in range(n+1)]
for idx, v in enumerate(l):
while len(stack)>0 and stack[-1][1] <= v:
stack.pop()
cnt[idx+1] += len(stack)
if len(stack) > 0 :
g = abs(stack[-1][0] - (idx+1))
if g < near[idx+1][1]:
near[idx+1][0] = stack[-1][0]
near[idx+1][1] = g
elif g == near[idx+1][1] and stack[-1][0] < near[idx+1][0]:
near[idx+1][0] = stack[-1][0]
stack.append([idx+1,v])
stack = []
for idx,v in reversed(list(enumerate(l))):
while len(stack) >0 and stack[-1][1] <=v:
stack.pop()
cnt[idx+1] += len(stack)
if len(stack) > 0 :
g = abs(stack[-1][0] - (idx+1))
if g < near[idx+1][1]:
near[idx+1][0] = stack[-1][0]
near[idx+1][1] = g
elif g == near[idx+1][1] and stack[-1][0] < near[idx+1][0]:
near[idx+1][0] = stack[-1][0]
stack.append([idx+1,v])
for i in range(1,n+1):
if cnt[i]>0:
print(str(cnt[i])+' '+str(near[i][0]))
else:
print(0)
near배열은 near[a][0]의 경우 a 건물에서 가장 가까운 건물 번호를 나타내며, near[a][1]의 경우에는 가장 가가운 건물의 거리를 나타내는 배열이다.monotone stack을 이용해 단조감소 하도록 구현 하였고, 현재 stack에 저장된 값들은 현재 건물에서 좌측 혹은 우측으로 보이는 건물들의 수이고, stack의 마지막 값은 가장 가까운 건물이다.