Official

C - Topological Sort Editorial by toam


条件を満たすグラフを \(G\) とします.トポロジカル順序の条件から, \(P\) において \(a\)\(b\) より先に登場するような \((a,b)\) に対して, \(b\to a\) のような有向辺は存在しません.すなわち,各 \(i\) に対して \(P_i\) から出る有向辺の終点は \(P_{i+1},\ldots,P_N\) のいずれかです.

さらに,頂点集合が \(P_1,P_2,\ldots,P_i\) であるような \(G\) の誘導部分グラフを \(G_i\) とします.このとき, \(G_i\) を辞書順最小トポロジカルソートしたとき, \((P_1,\ldots,P_i)\) である必要があります.( \(P_{i+1}\) 以降の頂点およびそれを端点とする有向辺をどのように \(G_i\) に追加しても, \(G_i\) 内のトポロジカル順序は変化しないため).

以上を踏まえたうえで,頂点 \(P_1,P_2,\ldots\) の順に,その頂点に入る辺の集合を決めていくことにします.

\(i\) に対し, \(P_j\gt P_i, j\lt i\) を満たす最大の \(j\) をとります.(そのような \(j\) が存在しない場合,頂点 \(i\) に入る有向辺の貼り方は任意であり, \(2^{i-1}\) 通りです.)このとき,頂点 \(P_j\) から頂点 \(P_i\) の間には有向パスが必要です.頂点 \(P_j\) から 頂点 \(P_j,P_{j+1},\ldots,P_{i-1}\) それぞれへの有向パスが存在するため,頂点 \(P_i\) への有向辺について少なくとも頂点 \(P_j,P_{j+1},\ldots,P_{i-1}\) のいずれかとの間に必要です.また,頂点 \(P_1,\ldots,P_{j-1}\) それぞれとの頂点との間の辺については任意です.よって,頂点 \(P_i\) に入る辺の集合は \(2^{i-1}-2^{j-1}\) 通りです.

\(i\) に対し, \(P_j\gt P_i, j\lt i\) を満たす最大の \(j\) は stack を用いることで全体で \(O(N)\) で求められます.

実装例(Python)

mod = 998244353
n = int(input())
p = list(map(int, input().split()))
ans = 1
stc = []
for i in range(n):
    while stc and p[stc[-1]] < p[i]:
        stc.pop()
    ans *= pow(2, i, mod) - (pow(2, stc[-1], mod) if stc else 0)
    ans %= mod
    stc.append(i)
print(ans)

posted:
last update: