公式

C - No Collision Moves 解説 by sounansya


まず、 \(S_i < S_j\) かつ \(T_i > T_j\) なる人 \((i,j)\) の組が存在する場合答えは No です。なぜなら、人 \(i,j\) の一方が最初に移動するタイミングで必ずもう一方と喧嘩になってしまうからです。この判定は \((S_1,T_1),(S_2,T_2),\ldots,(S_N,T_N)\)\(S\) の昇順にソートした際に \(T\) の値が昇順になっているかで判定すれば良いです。

以降はこのような人 \((i,j)\) の組が存在しない場合を考えます。

\(S_i < T_i\) を満たす人 \(i\) の集合を \(X\)\(S_i > T_i\) を満たす人 \(i\) の集合を \(Y\) とします。この時、上の条件より \(i \in X, j \in Y\) に対し \([S_i , T_i] \cap [T_j , S_j] = \emptyset\) が成立します。したがって、\(X\)\(Y\) それぞれ独立した問題として考えて良いです。

\(X\) に属する人のみで問題を考えると、条件より \(S\) の値が大きい人から順に移動させていくことで喧嘩が発生しない移動が達成できます。同様に、\(Y\) についても \(S\) の値が小さい人から順に移動させていけば良いです。

以上を適切に実装することでこの問題に正答することができます。計算量は \(O(N \log N)\) です。

実装例(Python3)

n = int(input())
ch = [() for _ in range(n)]
c1 = []
c2 = []
for i in range(n):
    s, t = map(int, input().split())
    ch[i] = (s, t)
    if s < t:
        c1.append((s, i))
    else:
        c2.append((s, i))
ch.sort()
for i in range(n - 1):
    if ch[i][1] > ch[i + 1][1]:
        print("No")
        exit()
c1.sort(reverse=True)
c2.sort()
ans = []
for s, i in c1:
    ans.append(i + 1)
for s, i in c2:
    ans.append(i + 1)
print("Yes")
print(*ans)

投稿日時:
最終更新: