公式
G - Buildings 解説
by
G - Buildings 解説
by
toam
各 \(i\) に対して条件を満たす \(j\) を昇順に並べた列を \(J_i\) とします.\(H_{J_{i,1}}\lt H_{J_{i,2}}\lt H_{J_{i,3}}\lt \ldots\ \cdots (1)\) が成り立っています.
\(i\neq N\) として \(J_{i+1}\) と \(J_i\) の差分に注目します.\(J_i\) は \(i+1\) を必ず含みます.このとき,\(H_{i+1}\gt H_j\) となるような \(j\in J_{i+1}\) は \(J_i\) には含まれません.一方で \(H_{i+1}\lt H_j\) となるような \(j\in J_{i+1}\) は \(J_i\) にも含まれます.\((1)\) が成り立っていることから,次のような手順で \(J_{i+1}\) から \(J_i\) を得ることができます.
- \(A=J_{i+1}\) とする.
- \(A\) が空でない限り,以下の操作を続ける.
- \(A\) の先頭の要素を \(j\) とする.\(H_{i+1}\gt H_j\) なら \(A\) から \(j\) を削除する.
- そうでないなら,この操作を終了する.
- \(A\) の先頭に \(i+1\) を追加する.
- この手順で得られた \(A\) が \(J_i\) である.
実際には先頭の要素を出し入れするよりも末尾の要素を出し入れする方が容易なため,\(J_i\) を逆順にして管理すると良いです.stack などを用いて実装することができます.計算量について,各 \(j\) が出し入れされる回数は高々 \(1\) 回なので,合計で \(O(N)\) になります.
n = int(input())
h = list(map(int, input().split()))
ans = [0] * n
stc = []
for i in range(n - 2, -1, -1):
while stc and h[stc[-1]] < h[i + 1]:
stc.pop()
stc.append(i + 1)
ans[i] = len(stc)
print(*ans)
投稿日時:
最終更新: