黒ココアさんのメモ置き場

メモを置いたり置かなかったり

ABC344 E - Insert or Erase

atcoder.jp

問題

  • 長さ$N$の数列$A$が与えられるよ
  • Q個のクエリを順番に処理してね
    • クエリ1:$A$の中の要素$x$の直後に$y$を挿入してね
    • クエリ2:$A$の中にある要素$x$を削除してね
  • 全部のクエリを捌いた後の$A$はどうなってる?

成約

  • $1 \leq N \leq 2 \times 10^{5}$
  • $1 \leq Q \leq 2 \times 10^{5}$
  • $A$の中の要素は常にユニーク
  • クエリが与えられた時、$A$の中に$x$は絶対存在するよ

思考

  • 電車の類題(ABC225D)を思い出す
  • 特定の要素の、「前の数字は何?」と、「後ろの数字は何?」を管理・更新していくと良さそう
    • クエリ1の捌き方:
      • 「$x$の後ろの数字」をメモ(tmp)
      • 「$y$の前の数字」を$x$に更新(新規作成)
      • 「$y$の後ろの数字」を「$x$の後ろだった数字(tmp)」に更新(新規作成)
      • 「$x$の後ろの数字」を$y$に更新
      • 「$x$の後ろだった数字(tmp)の、前の数字」を、$y$に更新
    • クエリ2の捌き方:
      • 「$x$の後ろの数字」を、「$x$の後ろの後ろの数字」に更新
      • 「$x$の前の前の数字」を、$x$に更新
  • 本番は$N=1$のケースでめっちゃしばかれました(5ペナ)
    • tips: 番兵として、先頭と末尾の車両を固定で置いておくと幸せになれました

コード

N = int(input())
A_L = [0] + list(map(int, input().split())) + [-1]

link_d = dict()
for i in range(1, N + 1):
    link_d[A_L[i]] = [A_L[i - 1], A_L[i + 1]]
link_d[0] = [None, A_L[1]]
link_d[-1] = [A_L[N], None]

Q = int(input())

for _ in range(Q):
    query = list(map(int, input().split()))

    if query[0] == 1:
        prev_num, add_num = query[1:]
        next_num = link_d[prev_num][1]

        link_d[prev_num][1] = add_num
        link_d[add_num] = [prev_num, next_num]
        link_d[next_num][0] = add_num

    else:
        del_num = query[1]
        prev_num, next_num = link_d[del_num]

        link_d[prev_num][1] = next_num
        link_d[next_num][0] = prev_num

ans_L = []
now_num = 0

while True:
    ans_L.append(now_num)
    if link_d[now_num][1] == -1:
        break
    now_num = link_d[now_num][1]
print(*ans_L[1:])