Official

E - 見通しの良い山並み / A Mountain Range with Clear Visibility Editorial by sounansya Editorial for printing


まず、数え上げるペア \((i,j)\) に新たに \(H_i > H_j\) という制約を足し、以下の条件を全て満たすペアを数え上げることを考えます。

  • \(1\le i < j \le N\)
  • \(C_i = C_j\)
  • \(i < k \le j\) に対し \(H_i>H_k\)

\(i\) を固定すると、\(3\) 番目の条件を満たす \(j\) は \(i\) を左端に持つ区間となり、その右端は SegTree 上の二分探索などで求めることができます。さらに、その区間の中で \(C_i=C_j\) を満たす \(j\) の個数は各色の index を保持した配列を持つことで二分探索により対数時間で計算することができます。

\(H_i < H_j\) に関しても同様に計算することができます。\(C,H\) を逆順にして \(2\) 回計算する実装が楽だと思います。

実装例(Python3)

from bisect import bisect_left
from atcoder.segtree import SegTree

n = int(input())
c = [0] * n
h = [0] * n
for i in range(n):
    c[i], h[i] = map(int, input().split())
    c[i] -= 1
ans = 0
for _ in range(2):
    g = [[] for _ in range(n)]
    for i in range(n):
        g[c[i]].append(i)
    seg = SegTree(max, -1, h)
    for i in range(n):
        j = seg.max_right(i, lambda x: x <= h[i])
        ans += bisect_left(g[c[i]], j) - bisect_left(g[c[i]], i + 1)
    c.reverse()
    h.reverse()
print(ans)

posted:
last update: