277
1 / 277 Masaki Hara (qnighy) 2013情報オリンピック春期トレーニング合宿にて

Spaceships 解説

Embed Size (px)

DESCRIPTION

2013年の情報オリンピック春期トレーニング合宿(日本代表選抜合宿)の4日目に出題されたSpaceshipsの解説です。問題文等は http://www.ioi-jp.org/camp/2013/2013-sp-tasks/index.html で入手できます。

Citation preview

Page 1: Spaceships 解説

1 / 277

Masaki Hara (qnighy)

2013年 情報オリンピック春期トレーニング合宿にて

Page 2: Spaceships 解説

2 / 277

有向木がたくさんあります

以下のクエリに高速で答えてください

1. Aの親をBにする ◦ Aは木の根で、BはAの子孫ではない

2. Aを親から切り離して木の根にする

3. A,Bが同じ木に属するか判定し、 同じ木に属する場合はLCAを求める

Page 3: Spaceships 解説

3 / 277

有向木がたくさんあります

J

F

L G

B

D

I

C

K

E

A H

Page 4: Spaceships 解説

4 / 277

有向木がたくさんあります

以下のクエリに高速で答えてください

J

F

L G

B

D

I

C

K

E

A H

Page 5: Spaceships 解説

5 / 277

1. Fの親をBにする

J

F

L G

B

D

I

C

K

E

A H

Page 6: Spaceships 解説

6 / 277

1. Fの親をBにする

J

F

L G

B

D

I

C

K

E

A H

Page 7: Spaceships 解説

7 / 277

1. Eの親をDにする

J

F

L G

B

D

I

C

K

E

A H

Page 8: Spaceships 解説

8 / 277

1. Eの親をDにする

J

F

L G

B

D

I

C

K

E

A H

Page 9: Spaceships 解説

9 / 277

2. Iを親から切り離して根にする

J

F

L G

B

D

I

C

K

E

A H

Page 10: Spaceships 解説

10 / 277

2. Iを親から切り離して根にする

J

F

L G

B

D

I

C

K

E

A H

Page 11: Spaceships 解説

11 / 277

2. Lを親から切り離して根にする

J

F

L G

B

D

I

C

K

E

A H

Page 12: Spaceships 解説

12 / 277

2. Lを親から切り離して根にする

J

F

L G

B

D

I

C

K

E

A H

Page 13: Spaceships 解説

13 / 277

3. GとHのLCAを求める

J

F

L G

B

D

I

C

K

E

A H

Page 14: Spaceships 解説

14 / 277

3. GとHのLCAを求める ◦ LCA: 最小共通先祖

J

F

L G

B

D

I

C

K

E

A H

Page 15: Spaceships 解説

15 / 277

頂点数 𝑁 ≤ 5000

クエリ数 𝑄 ≤ 5000

Page 16: Spaceships 解説

16 / 277

各頂点は親リンクを覚えておく

クエリ1,2に対しては普通に答える

F

B

Page 17: Spaceships 解説

17 / 277

各頂点は親リンクを覚えておく

クエリ3に対しては

J

F

L G

B

D

I

C

K

E

A H

Page 18: Spaceships 解説

18 / 277

各頂点は親リンクを覚えておく

クエリ3に対しては ◦ Gから根に向かって辿る

J

F

L G

B

D

I

C

K

E

A H

Page 19: Spaceships 解説

19 / 277

各頂点は親リンクを覚えておく

クエリ3に対しては ◦ Gから根に向かって辿る

◦ Hから根に向かって辿る

J

F

L G

B

D

I

C

K

E

A H

Page 20: Spaceships 解説

20 / 277

各頂点は親リンクを覚えておく

クエリ3に対しては ◦ Gから根に向かって辿る

◦ Hから根に向かって辿る

◦ 並べる

F

G

B

D

K

E

H

Page 21: Spaceships 解説

21 / 277

各頂点は親リンクを覚えておく

クエリ3に対しては ◦ Gから根に向かって辿る

◦ Hから根に向かって辿る

◦ 並べる

F G B

D K E H

D K

Page 22: Spaceships 解説

22 / 277

各頂点は親リンクを覚えておく

クエリ3に対しては ◦ Gから根に向かって辿る

◦ Hから根に向かって辿る

◦ 根からの順番で並べる

◦ 一致する中で最も後ろのものを選ぶ

F G B

D K E H

D K

Page 23: Spaceships 解説

23 / 277

各頂点は親リンクを覚えておく

クエリ3に対しては ◦ Gから根に向かって辿る

◦ Hから根に向かって辿る

◦ 根からの順番で並べる

◦ 根が一致しないときは-1

Page 24: Spaceships 解説

24 / 277

頂点数 𝑁 ≤ 5000

クエリ数 𝑄 ≤ 5000

計算量は𝑂(𝑁𝑄)なので間に合う

Page 25: Spaceships 解説

25 / 277

頂点数 𝑁 ≤ 106

クエリ数 𝑄 ≤ 106

辺の削除は行われない

Page 26: Spaceships 解説

26 / 277

CがAとBのLCA

A

D

C

B

F

E

Page 27: Spaceships 解説

27 / 277

CがAとBのLCA ↓辺を追加

A

D

C

B

F

E

Page 28: Spaceships 解説

28 / 277

CがAとBのLCA ↓辺を追加

Cは依然としてAとBのLCA

A

D

C

B

F

E

Page 29: Spaceships 解説

29 / 277

CがAとBのLCA ↓辺を追加

Cは依然としてAとBのLCA

最終的にできる木の上でLCAを計算できればよい

Page 30: Spaceships 解説

30 / 277

木の嬉しい順序(DFS順序) ◦ Preorder –頂点に入るときに記録する順序

A, B, D, E, C, F

D

B

A

E

C

F

Page 31: Spaceships 解説

31 / 277

木の嬉しい順序(DFS順序) ◦ Postorder – 頂点から出るときに記録する順序

D, E, B, F, C, A

D

B

A

E

C

F

Page 32: Spaceships 解説

32 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

Page 33: Spaceships 解説

33 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A,

Page 34: Spaceships 解説

34 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B,

Page 35: Spaceships 解説

35 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B, D,

Page 36: Spaceships 解説

36 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B, D, B,

Page 37: Spaceships 解説

37 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B, D, B, E

Page 38: Spaceships 解説

38 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B, D, B, E, B,

Page 39: Spaceships 解説

39 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B, D, B, E, B, A,

Page 40: Spaceships 解説

40 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B, D, B, E, B, A, C,

Page 41: Spaceships 解説

41 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B, D, B, E, B, A, C, F,

Page 42: Spaceships 解説

42 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B, D, B, E, B, A, C, F, C,

Page 43: Spaceships 解説

43 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

頂点から入るときに記録し、

頂点から出るときにも 自分の親を記録する順序

D

B

A

E

C

F

A, B, D, B, E, B, A, C, F, C, A

Page 44: Spaceships 解説

44 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

木の辺を、行きと帰りの2つの辺から なるとみなすときの オイラー閉路に対応する

D

B

A

E

C

F

A, B, D, B, E, B, A, C, F, C, A

Page 45: Spaceships 解説

45 / 277

木の嬉しい順序(DFS順序) ◦ Euler Tour

木の辺を、行きと帰りの2つの辺から なるとみなすときの オイラー閉路に対応する

オイラー閉路 (Euler Tour) : 全ての辺を1度ずつ通る閉路

オイラー路はケーニヒスベルクの橋問題で有名

Wikipediaより。 CC3.0-BY-SA

Page 46: Spaceships 解説

46 / 277

Euler TourによるLCAの計算

D

B

A

E

C

F

Page 47: Spaceships 解説

47 / 277

Euler TourによるLCAの計算

D

B

A

E

C

F

A B D B E B A C F C A

1 2 3 2 3 2 1 2 3 2 1

Page 48: Spaceships 解説

48 / 277

Euler TourによるLCAの計算

D

B

A

E

C

F

A B D B E B A C F C A

1 2 3 2 3 2 1 2 3 2 1

Page 49: Spaceships 解説

49 / 277

Euler TourによるLCAの計算

D

B

A

E

C

F

A B D B E B A C F C A

1 2 3 2 3 2 1 2 3 2 1

Page 50: Spaceships 解説

50 / 277

Euler TourによるLCAの計算

D

B

A

E

C

F

A B D B E B A C F C A

1 2 3 2 3 2 1 2 3 2 1

Page 51: Spaceships 解説

51 / 277

Euler TourによるLCAの計算

D

B

A

E

C

F

A B D B E B A C F C A

1 2 3 2 3 2 1 2 3 2 1

深さ最小

Page 52: Spaceships 解説

52 / 277

Euler TourによるLCAの計算

RMQを利用

D

B

A

E

C

F

A B D B E B A C F C A

1 2 3 2 3 2 1 2 3 2 1

深さ最小

Page 53: Spaceships 解説

53 / 277

正当性

Page 54: Spaceships 解説

54 / 277

正当性: CがAとBのLCAのとき ◦ Euler Tour上でCは[A,B]に含まれる

◦ Euler Tour上で[A,B]に含まれるのはCの部分木

を言えばよい

Page 55: Spaceships 解説

55 / 277

正当性(1): Euler Tour上でCは[A,B]に含まれる ◦ AからBに行くにはCを経由しないといけない(LCAの性質より)

◦ ので当たり前

Page 56: Spaceships 解説

56 / 277

正当性(2): Euler Tour上で[A,B]に含まれるのは Cの部分木 ◦ Euler Tourにおいて部分木は連続した部分列として現れる

◦ ので当たり前

Page 57: Spaceships 解説

57 / 277

LCAを求めて終わり?

Page 58: Spaceships 解説

58 / 277

LCAを求めて終わり? ◦ あと少しだけやることがあります

Page 59: Spaceships 解説

59 / 277

「削除がない場合の利点」の考察を思い出す

Page 60: Spaceships 解説

60 / 277

「削除がない場合の利点」の考察を思い出す

LCAが存在するなら、最終的な木の上で計算すればよい

Page 61: Spaceships 解説

61 / 277

「削除がない場合の利点」の考察を思い出す

LCAが存在するなら、最終的な木の上で計算すればよい

Page 62: Spaceships 解説

62 / 277

A, Bが同じ木上にあるかどうかの判定が必要

Page 63: Spaceships 解説

63 / 277

A, Bが同じ木上にあるかどうかの判定が必要

ですが

Page 64: Spaceships 解説

64 / 277

A, Bが同じ木上にあるかどうかの判定が必要

ですが

辺の追加クエリしかないのでUnionFindでよい ということはすぐにわかると思います

Page 65: Spaceships 解説

65 / 277

頂点数 𝑁 ≤ 106

クエリ数 𝑄 ≤ 106

辺の削除は行われない

𝑂(𝑁 + 𝑄 log𝑁) なので間に合う

Page 66: Spaceships 解説

66 / 277

ここまでの両方を実装すれば40点

Page 67: Spaceships 解説

67 / 277

ここまでの両方を実装すれば40点

複数のアルゴリズムを条件によって使い分けるテクは さすがに使っていると思います

Page 68: Spaceships 解説

68 / 277

頂点数 𝑁 ≤ 106

クエリ数 𝑄 ≤ 106

Page 69: Spaceships 解説

69 / 277

頂点数 𝑁 ≤ 106

クエリ数 𝑄 ≤ 106

削除クエリもある

Page 70: Spaceships 解説

70 / 277

追加も削除もある場合の頻出テク

Page 71: Spaceships 解説

71 / 277

追加も削除もある場合の頻出テク ◦ クエリの(平方)分割

◦ がんばって動的になんとかする

Page 72: Spaceships 解説

72 / 277

追加も削除もある場合の頻出テク

◦ がんばって動的になんとかする

Page 73: Spaceships 解説

73 / 277

追加も削除もある場合の頻出テク

◦がんばって動的になんとかする

Page 74: Spaceships 解説

74 / 277

木が静的な場合のLCA (復習)

Page 75: Spaceships 解説

75 / 277

木が静的な場合のLCA (復習) ◦ Euler Tour上で必要とされるクエリは以下の通り

Page 76: Spaceships 解説

76 / 277

木が静的な場合のLCA (復習) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

Page 77: Spaceships 解説

77 / 277

木が静的な場合のLCA (復習) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

◦ RMQで実現可能

Page 78: Spaceships 解説

78 / 277

木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

2.

◦ RMQで実現可能な気がする

Page 79: Spaceships 解説

79 / 277

木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

2. 列の連結をする

3.

◦ RMQで実現可能な気がする

Page 80: Spaceships 解説

80 / 277

木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

2. 列の連結をする

3. 列の分割をする

4.

◦ RMQで実現可能な気がする

Page 81: Spaceships 解説

81 / 277

木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

2. 列の連結をする

3. 列の分割をする

4. それだけ?

Page 82: Spaceships 解説

82 / 277

木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

2. 列の連結をする

3. 列の分割をする

4. 区間に値を足す

Page 83: Spaceships 解説

83 / 277

木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

2. 列の連結をする

3. 列の分割をする

4. 区間に値を足す

◦ この業界では「Starry Sky木」として知られているもの

Page 84: Spaceships 解説

84 / 277

木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

2. 列の連結をする

3. 列の分割をする

4. 区間に値を足す

◦ この業界では「Starry Sky木」として知られているもの を平衡二分木として実装する必要がある (絶望)

Page 85: Spaceships 解説

85 / 277

木が動的な場合のLCA (絶望) ◦ Euler Tour上で必要とされるクエリは以下の通り

1. 区間の最小値をとる

2. 列の連結をする

3. 列の分割をする

4. 区間に値を足す

◦ この業界では「Starry Sky木」として知られているもの を平衡二分木として実装する必要がある (絶望)

しかもmerge/splitベースで

Page 86: Spaceships 解説

86 / 277

平衡二分木の中身は後回し

Page 87: Spaceships 解説

87 / 277

平衡二分木の中身は後回し

平衡二分木を使った具体的な実装方法

Page 88: Spaceships 解説

88 / 277

木の各頂点ごとに、Euler Tourのためのノードを2つ用意する(𝑆𝐴, 𝐺𝐴) ◦ 𝑆𝐴上には頂点Aの番号と、その深さが記録されている

◦ 𝐺𝐴上には頂点Aの親Pの番号と、その深さが記録されている

◦ Aが根のときは𝑆𝐴のみ使う

A

B 𝑆𝐴

A

B

𝐺𝐵

Page 89: Spaceships 解説

89 / 277

木の連結

B

D E

A

C

F

𝑆𝐵 𝐵 , 𝑆𝐷 𝐷 , 𝐺𝐷 𝐵 , 𝑆𝐸 𝐸 , 𝐺𝐸(𝐵)

𝑆𝐴 𝐴 , 𝑆𝐶 𝐶 , 𝑆𝐹 𝐹 , 𝐺𝐹 𝐶 , 𝐺𝐹(𝐴)

Depth 0

Depth 0

Depth 1 Depth 1 Depth 2

Depth 1

Page 90: Spaceships 解説

90 / 277

木の連結 1. Euler TourをA点で分割

◦ A直下ならどの位置でもいい

𝑆𝐴の直後がおすすめ B

D E

A

C

F

𝑆𝐵 𝐵 , 𝑆𝐷 𝐷 , 𝐺𝐷 𝐵 , 𝑆𝐸 𝐸 , 𝐺𝐸(𝐵)

𝑆𝐴 𝐴 ,                           𝑆𝐶 𝐶 , 𝑆𝐹 𝐹 , 𝐺𝐹 𝐶 , 𝐺𝐹(𝐴)

Depth 0

Depth 0

Depth 1 Depth 1 Depth 2

Depth 1

Page 91: Spaceships 解説

91 / 277

木の連結 1. Euler TourをA点で分割

2. Euler Tourを挿入

B

D E

A

C

F

𝑆𝐴 𝐴 , 𝑆𝐵 𝐵 , 𝑆𝐷 𝐷 , 𝐺𝐷 𝐵 , 𝑆𝐸 𝐸 , 𝐺𝐸 𝐵 , 𝐺𝐵(𝐸), 𝑆𝐶 𝐶 , 𝑆𝐹 𝐹 , 𝐺𝐹 𝐶 , 𝐺𝐹(𝐴)

Depth 0

Depth 0

Depth 1 Depth 1 Depth 2

Depth 1

Page 92: Spaceships 解説

92 / 277

木の連結 1. Euler TourをA点で分割

2. Euler Tourを挿入

3. 深さを調整 B

D E

A

C

F

𝑆𝐴 𝐴 , 𝑆𝐵 𝐵 , 𝑆𝐷 𝐷 , 𝐺𝐷 𝐵 , 𝑆𝐸 𝐸 , 𝐺𝐸 𝐵 , 𝐺𝐵(𝐸), 𝑆𝐶 𝐶 , 𝑆𝐹 𝐹 , 𝐺𝐹 𝐶 , 𝐺𝐹(𝐴)

Depth 0

Depth 1

Depth 2 Depth 2 Depth 2

Depth 1

Page 93: Spaceships 解説

93 / 277

木の削除: 追加のときと逆操作

Page 94: Spaceships 解説

94 / 277

平衡Starry Sky Treeがあればよいことがわかった

Page 95: Spaceships 解説

95 / 277

平衡Starry Sky Treeがあればよいことがわかった

ではどのように実装するか?(実装例)

Page 96: Spaceships 解説

96 / 277

今回は、葉ノードと内部ノードの区別をしない ◦ A,B,C,D,Eはどれも列上の項目とする

B

A

D

E

C

Page 97: Spaceships 解説

97 / 277

各ノードは、Δ𝑥𝐴というフィールドを持つ

B

A

D

E

C

Page 98: Spaceships 解説

98 / 277

各ノードは、Δ𝑥𝐴というフィールドを持つ

各ノードに定めたい値𝑥𝐴は、

𝑥𝐴 = Δ𝑥𝐴

𝐴から根までのパス上のノード

B

A

D

E

C

Page 99: Spaceships 解説

99 / 277

𝑥𝐴 = Δ𝑥𝐷 + Δ𝑥𝐵 + Δ𝑥𝐴

𝑥𝐵 = Δ𝑥𝐷 + Δ𝑥𝐵

𝑥𝐶 = Δ𝑥𝐷 + Δ𝑥𝐵 + Δ𝑥𝐶

𝑥𝐷 = Δ𝑥𝐷

𝑥𝐸 = Δ𝑥𝐷 + Δ𝑥𝐸

B

A

D

E

C

Page 100: Spaceships 解説

100 / 277

木の回転: 𝑥𝐴が保存されるように行う

Δ𝑥𝐴′ = 𝑥𝐴 − 𝑥𝐵

Δ𝑥𝐵′ = 𝑥𝐵

Δ𝑥𝐶′ = 𝑥𝐶 − 𝑥𝐷

Δ𝑥𝐷′ = 𝑥𝐷 − 𝑥𝐵

Δ𝑥𝐸′ = 𝑥𝐸 − 𝑥𝐷 D

C

B

A

E

Page 101: Spaceships 解説

101 / 277

木の回転: 𝑥𝐴が保存されるように行う

Δ𝑥𝐴′ = Δ𝑥𝐴

Δ𝑥𝐵′ = Δ𝑥𝐷 + Δ𝑥𝐵

Δ𝑥𝐶′ = Δ𝑥𝐵 + Δ𝑥𝐶

Δ𝑥𝐷′ = −Δ𝑥𝐵

Δ𝑥𝐸′ = Δ𝑥𝐸 D

C

B

A

E

Page 102: Spaceships 解説

102 / 277

最後に、ノードに値𝑦𝐴を

𝑦𝐴 = min𝐴の全ての子孫𝐵

𝑥𝐵 − 𝑥𝐴

となるように計算して保持しておく

Page 103: Spaceships 解説

103 / 277

最後に、ノードに値𝑦𝐴を

𝑦𝐴 = min𝐴の全ての子孫𝐵

𝑥𝐵 − 𝑥𝐴

となるように計算して保持しておく

これでStarry Sky Tree相当の計算を行えるようになる

Page 104: Spaceships 解説

104 / 277

平衡二分木の基本

Page 105: Spaceships 解説

105 / 277

平衡二分木の基本:回転操作

Page 106: Spaceships 解説

106 / 277

回転操作: 順序を保存したまま木構造を変形

Page 107: Spaceships 解説

107 / 277

回転操作: 順序を保存したまま木構造を変形

次のような二分木を考える

B

C

D

E

A

Page 108: Spaceships 解説

108 / 277

回転操作: 順序を保存したまま木構造を変形

次のような二分木を考える

順序: 左の子孫→自分→右の子孫

B

C

D

E

A

Page 109: Spaceships 解説

109 / 277

回転操作: 順序を保存したまま木構造を変形

次のような二分木を考える

順序: 左の子孫→自分→右の子孫

この場合は A, B, C, D, E の順番 B

C

D

E

A

Page 110: Spaceships 解説

110 / 277

次のように変形しても順番はA,B,C,D,E

B

C

D

E

A

D

E

B

A

C

Page 111: Spaceships 解説

111 / 277

次のように変形しても順番はA,B,C,D,E

これを「木の回転」と言う

B

C

D

E

A

D

E

B

A

C

Page 112: Spaceships 解説

112 / 277

次のように変形しても順番はA,B,C,D,E

これを「木の回転」と言う

うまく回転をすることで、偏りが起きないようにする二分木を「平衡二分木」と言う ◦ 回転以外の方法で平衡を保つものもある

Page 113: Spaceships 解説

113 / 277

平衡二分木の実装方法

Page 114: Spaceships 解説

114 / 277

平衡二分木の実装方法

今回は何でもOK! ◦ 赤黒木

◦ RBST

◦ Treap

◦ Splay木

◦ などなど…

Page 115: Spaceships 解説

115 / 277

この解説ではSplay木の説明をします

Page 116: Spaceships 解説

116 / 277

突然ですが、Union Findの復習をします

Page 117: Spaceships 解説

117 / 277

突然ですが、Union Findの復習をします

Union Find の効率化テクニック:

アクセスした頂点を根へ持っていく

B

D

A

F

E

C

Page 118: Spaceships 解説

118 / 277

突然ですが、Union Findの復習をします

Union Find の効率化テクニック:

アクセスした頂点を根へ持っていく

B

D

A

F

E

C

Page 119: Spaceships 解説

119 / 277

突然ですが、Union Findの復習をします

Union Find の効率化テクニック:

アクセスした頂点を根へ持っていく

B

D

A

F

E

C

Page 120: Spaceships 解説

120 / 277

突然ですが、Union Findの復習をします

Union Find の効率化テクニック:

アクセスした頂点を根へ持っていく

B

D

A

F

E

C

Page 121: Spaceships 解説

121 / 277

突然ですが、Union Findの復習をします

Union Find の効率化テクニック:

アクセスした頂点を根へ持っていく

B

D

A

F

E

C

Page 122: Spaceships 解説

122 / 277

突然ですが、Union Findの復習をします

Union Find の効率化テクニック:

アクセスした頂点を根へ持っていく

B

D

A

F

E

C

Page 123: Spaceships 解説

123 / 277

同じようなことを、二分探索木でもできないか?

Page 124: Spaceships 解説

124 / 277

同じようなことを、二分探索木でもできないか? ◦ →Move-to-root heuristic

Page 125: Spaceships 解説

125 / 277

Move-to-root heuristic ◦ 頂点にアクセスしたら、それが根に行くまで繰り返し回転する

Page 126: Spaceships 解説

126 / 277

Move-to-root heuristic ◦ 頂点にアクセスしたら、それが根に行くまで繰り返し回転する

◦ そんなので上手くいくわけないだろ!!

Page 127: Spaceships 解説

127 / 277

実際ダメ

Page 128: Spaceships 解説

128 / 277

実際ダメ

A

B

C

D

E

Page 129: Spaceships 解説

129 / 277

実際ダメ

A

B

C

D

E

Page 130: Spaceships 解説

130 / 277

実際ダメ

B

A

C

D

E

Page 131: Spaceships 解説

131 / 277

実際ダメ

B

C

A

D

E

Page 132: Spaceships 解説

132 / 277

実際ダメ

B

C

D

A

E

Page 133: Spaceships 解説

133 / 277

実際ダメ

B

C

D

E

A

Page 134: Spaceships 解説

134 / 277

実際ダメ

この後A, B, C, D, Eの順にアクセスしたら 𝑛 + 𝑛 − 1 + …+ 1 = 𝑂 𝑛2

のコストがかかってしまう

Page 135: Spaceships 解説

135 / 277

実際ダメ

この後A, B, C, D, Eの順にアクセスしたら 𝑛 + 𝑛 − 1 + …+ 1 = 𝑂 𝑛2

のコストがかかってしまう

どうする?

Page 136: Spaceships 解説

136 / 277

解決策: 木の回転を3つに分ける

Page 137: Spaceships 解説

137 / 277

解決策: 木の回転を3つに分ける ◦ “zig” step

◦ “zig-zag” step

◦ “zig-zig” step

Page 138: Spaceships 解説

138 / 277

(1) “zig”-step

Page 139: Spaceships 解説

139 / 277

(1) “zig”-step

すぐ上が根の場合

R

A

Page 140: Spaceships 解説

140 / 277

(1) “zig”-step

すぐ上が根の場合

普通に回転する

R

A

Page 141: Spaceships 解説

141 / 277

(2) “zig-zag”-step

Page 142: Spaceships 解説

142 / 277

(2) “zig-zag”-step

左→右、またはその逆のとき

P

A

G

Page 143: Spaceships 解説

143 / 277

(2) “zig-zag”-step

左→右、またはその逆のとき

普通に2回回転する

P

A

G

Page 144: Spaceships 解説

144 / 277

(2) “zig-zag”-step

左→右、またはその逆のとき

普通に2回回転する

P

A

G

Page 145: Spaceships 解説

145 / 277

(2) “zig-zag”-step

左→右、またはその逆のとき

普通に2回回転する

ここまでは先ほどと同じ

Page 146: Spaceships 解説

146 / 277

(3) “zig-zig”-step

Page 147: Spaceships 解説

147 / 277

(3) “zig-zig”-step

左→左、またはその逆のとき

P

A

G

Page 148: Spaceships 解説

148 / 277

(3) “zig-zig”-step

左→左、またはその逆のとき

2回ではなく3回回転する

P

A

G

Page 149: Spaceships 解説

149 / 277

(3) “zig-zig”-step

左→左、またはその逆のとき

2回ではなく3回回転する

P

A

G

Page 150: Spaceships 解説

150 / 277

(3) “zig-zig”-step

左→左、またはその逆のとき

2回ではなく3回回転する

P

A

G

Page 151: Spaceships 解説

151 / 277

(3) “zig-zig”-step

左→左、またはその逆のとき

2回ではなく3回回転する

(ただし、後でこれを2回として扱う)

P

A

G

Page 152: Spaceships 解説

152 / 277

Splaying operation ◦ 偏った位置にあるときだけ余計に回転する

Page 153: Spaceships 解説

153 / 277

Splaying operation ◦ 偏った位置にあるときだけ余計に回転する

◦ そんなので上手くいくわけないだろ!!

Page 154: Spaceships 解説

154 / 277

実は上手くいく

Page 155: Spaceships 解説

155 / 277

実は上手くいく

具体的には: 𝑂(log𝑁) amortized

Page 156: Spaceships 解説

156 / 277

実は上手くいく

具体的には: 𝑂(log𝑁) amortized

Page 157: Spaceships 解説

157 / 277

ならし計算量 (amortized time complexity)

N個の一連の操作が𝑂(𝑓(𝑁))で行えるとする

1つ1つの操作は、本当は𝑂(𝑓 𝑁

𝑁)とは限らない

これを𝑂(𝑓 𝑁

𝑁)として扱うのが、ならし計算量

Page 158: Spaceships 解説

158 / 277

ならし計算量のイメージ

ならし計算量

本当の計算量 操作1

操作2

操作3

操作4

操作5

Page 159: Spaceships 解説

159 / 277

ならし計算量の向き/不向き

Page 160: Spaceships 解説

160 / 277

ならし計算量の向き/不向き

向いているもの ◦ 全体での処理効率が重視されるバッチ型の処理

◦ 例: プログラミングコンテスト

向いていないもの ◦ リアルタイム性能が重視される処理

◦ 例: 信号処理

Page 161: Spaceships 解説

161 / 277

ならし計算量と平均計算量

Page 162: Spaceships 解説

162 / 277

ならし計算量と平均計算量 ◦ この2つは別物!!

◦ ならし計算量 : 時系列上での平均

◦ 平均計算量 : 確率変数上での平均

Page 163: Spaceships 解説

163 / 277

ならし計算量と平均計算量 ◦ この2つは別物!!

◦ ならし計算量 : 時系列上での平均

◦ 平均計算量 : 確率変数上での平均

◦ ならし計算量 : 不確定要素は無い!

Page 164: Spaceships 解説

164 / 277

Splayのならし計算量の評価

Page 165: Spaceships 解説

165 / 277

Splayのならし計算量の評価

「ポテンシャル関数」の概念を導入

Page 166: Spaceships 解説

166 / 277

Splayのならし計算量の評価

「ポテンシャル関数」の概念を導入 ◦ 借金みたいなもの

Page 167: Spaceships 解説

167 / 277

ポテンシャル関数を用いた計算量の均し(ならし)

𝑎𝑗 = 𝑡𝑗 +Φ𝑗+1 −Φj

◦ 𝑡𝑗 : その操作の実際の計算量

◦ Φ𝑗+1 −Φj : ポテンシャルの増加量

◦ 𝑎𝑗 : その操作のならし計算量

Page 168: Spaceships 解説

168 / 277

ポテンシャル関数を用いた計算量の均し(ならし)

𝑎𝑗 = 𝑡𝑗 +Φ𝑗+1 −Φj

◦ 𝑡𝑗 : その操作の実際の計算量

◦ Φ𝑗+1 −Φj : ポテンシャルの増加量

◦ 𝑎𝑗 : その操作のならし計算量

ポテンシャルの意味 ◦ より大きい: 木はより偏っている

◦ より小さい: 木はより平坦になっている

Page 169: Spaceships 解説

169 / 277

ならし計算量の総和をとる

𝑎𝑗𝑗 = 𝑡𝑗𝑗 +Φ𝑚 −Φ0

◦ 𝑡𝑗𝑗 : 実際の計算量の総和

◦ Φ𝑚 −Φ0 : ポテンシャルの総変化量

◦ 𝑎𝑗𝑗 : ならし計算量の総和

Page 170: Spaceships 解説

170 / 277

ならし計算量の総和をとる

𝑎𝑗𝑗 = 𝑡𝑗𝑗 +Φ𝑚 −Φ0

◦ 𝑡𝑗𝑗 : 実際の計算量の総和

◦ Φ𝑚 −Φ0 : ポテンシャルの総変化量

◦ 𝑎𝑗𝑗 : ならし計算量の総和

ポテンシャルの総変化量が小さければうまく評価できる

Page 171: Spaceships 解説

171 / 277

Splay木のポテンシャル ◦ Splay木の各頂点の重さを𝑤(𝑥)とする

計算量の見積もり方にあわせて自由に決めてよい

◦ Splay木の頂点のサイズ s 𝑥 = 𝑤(𝑦)𝑥の全ての子孫𝑦

◦ Splay木の頂点のランク 𝑟 𝑥 = log2 𝑠(𝑥)

◦ Splay木のポテンシャル Φ = 𝑟(𝑥)全ての頂点𝑥

Page 172: Spaceships 解説

172 / 277

Splay木のポテンシャル: 例

Page 173: Spaceships 解説

173 / 277

Splay木のポテンシャル: 例

重さ 𝑤(𝑥) (今回は全て1とする)

1

1

1

1

1

1

1

Page 174: Spaceships 解説

174 / 277

Splay木のポテンシャル: 例

サイズ 𝑠(𝑥) ◦ 部分木の重さの和

5

3

7

1

1

1

1

Page 175: Spaceships 解説

175 / 277

Splay木のポテンシャル: 例

ランク 𝑟 𝑥 = log2 𝑠(𝑥)

2.3

1.6

2.8

0.0

0.0

0.0

0.0

Page 176: Spaceships 解説

176 / 277

Splay木のポテンシャル: 例

ポテンシャル: ランクの総和

Φ = 2.8 + 2.3 + 1.6 = 6.7

Page 177: Spaceships 解説

177 / 277

Splay木のポテンシャルの良い性質

Page 178: Spaceships 解説

178 / 277

Splay木のポテンシャルの良い性質 …

回転の影響を受ける頂点が少ない ◦ 解析が簡単になる

Page 179: Spaceships 解説

179 / 277

アクセス補題 (Access Lemma)

Page 180: Spaceships 解説

180 / 277

アクセス補題 (Access Lemma)

𝑥 : 木のノード

𝑡 : 木の根 とするとき

木をsplayする操作一回にかかる時間(回転の回数)は、ならし計算量で

3𝑟 𝑡 − 3𝑟 𝑥 + 1

以下である。

Page 181: Spaceships 解説

181 / 277

アクセス補題の証明

Page 182: Spaceships 解説

182 / 277

アクセス補題の証明

各回転ステップのならし計算量が 1. “zig”-stepでは 3𝑟′ 𝑥 − 3𝑟 𝑥 + 1 以下

2. それ以外では 3𝑟′ 𝑥 − 3𝑟(𝑥) 以下

(ただし、𝑟′(𝑥) : 操作後のランク)

であることを示す。

そうすると、1のケースに登場する𝑟′(𝑥)は初期の𝑟(𝑡)と等しい(木全体のサイズの対数)ので、合計すると3𝑟 𝑡 − 3𝑟 𝑥 + 1になる。

Page 183: Spaceships 解説

183 / 277

アクセス補題の証明 (1) “zig”-step の場合

𝑟 𝑋 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 )

𝑟 𝑅 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅))

X

B

R

C

A

Page 184: Spaceships 解説

184 / 277

アクセス補題の証明 (1) “zig”-step の場合

𝑟 𝑋 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 )

𝑟′ 𝑋 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 +𝑤 𝐶 + 𝑤 𝑅 )

𝑟 𝑅 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅))

𝑟′ 𝑅 = log2(𝑤 𝑅 + 𝑤 𝐵 + 𝑤 𝐶 )

X

B

R

C

A

Page 185: Spaceships 解説

185 / 277

アクセス補題の証明 (1) “zig”-step の場合

𝑟 𝑋 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 )

𝑟′ 𝑋 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 +𝑤 𝐶 + 𝑤 𝑅 )

𝑟 𝑅 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅))

𝑟′ 𝑅 = log2(𝑤 𝑅 + 𝑤 𝐵 + 𝑤 𝐶 )

Page 186: Spaceships 解説

186 / 277

アクセス補題の証明 (1) “zig”-step の場合

𝑟 𝑋 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 )

𝑟′ 𝑋 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 +𝑤 𝐶 + 𝑤 𝑅 )

𝑟 𝑅 = log2(𝑤 𝑋 + 𝑤 𝐴 + 𝑤 𝐵 + 𝑤 𝐶 + 𝑤(𝑅))

𝑟′ 𝑅 = log2(𝑤 𝑅 + 𝑤 𝐵 + 𝑤 𝐶 )

𝑟 𝑋 ≤ 𝑟′ 𝑋 , 𝑟′ 𝑅 ≤ 𝑟(𝑅)

Page 187: Spaceships 解説

187 / 277

アクセス補題の証明 (1) “zig”-step の場合

𝑟 𝑋 ≤ 𝑟′ 𝑋 , 𝑟′ 𝑅 ≤ 𝑟(𝑅)

ならし計算量

𝑎 = 𝑡 + Φ′ −Φ= 1 + 𝑟′ 𝑋 + 𝑟′ 𝑅 − 𝑟 𝑋 − 𝑟 𝑅

≤ 1 + 𝑟′ 𝑋 − 𝑟 𝑋≤ 1 + 3𝑟′ 𝑋 − 3𝑟 𝑋

Page 188: Spaceships 解説

188 / 277

アクセス補題の証明 (2) “zigzig”-step の場合

𝑟 𝑋 = log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 )

𝑟 𝑃 = log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤(𝑃))

𝑟 𝐺 =log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑠 𝐷 + 𝑤 𝐺 )

X

B

P

C

A

G

D

Page 189: Spaceships 解説

189 / 277

アクセス補題の証明 (2) “zigzig”-step の場合

𝑟 𝑋 = log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 )

𝑟′ 𝑋 =log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝑃 + 𝑤 𝐺 )

𝑟 𝑃 = log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤(𝑃))

𝑟′ 𝑃 = log2(𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑤 𝐺 )

𝑟 𝐺 =log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑠 𝐷 + 𝑤 𝐺 )

𝑟′ 𝐺 = log2(𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝐺 )

X

B

P

C

A

G

D

Page 190: Spaceships 解説

190 / 277

アクセス補題の証明 (2) “zigzig”-step の場合

𝑟 𝑋 = log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 )

𝑟′ 𝑋 =log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝑃 + 𝑤 𝐺 )

𝑟 𝑃 = log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤(𝑃))

𝑟′ 𝑃 = log2(𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑤 𝐺 )

𝑟 𝐺 =log2(𝑤 𝑋 + 𝑠 𝐴 + 𝑠 𝐵 + 𝑠 𝐶 + 𝑤 𝑃 + 𝑠 𝐷 + 𝑤 𝐺 )

𝑟′ 𝐺 = log2(𝑠 𝐶 + 𝑠 𝐷 + 𝑤 𝐺 )

Page 191: Spaceships 解説

191 / 277

アクセス補題の証明 (2) “zigzig”-step の場合

𝑟′ 𝑋 = 𝑟 𝐺 , 𝑟′ 𝑋 ≤ 𝑟′ 𝑃 , 𝑟 𝑃 ≤ 𝑟 𝑋

Page 192: Spaceships 解説

192 / 277

アクセス補題の証明 (2) “zigzig”-step の場合

𝑟′ 𝑋 = 𝑟 𝐺 , 𝑟′ 𝑃 ≤ 𝑟′ 𝑋 , 𝑟 𝑋 ≤ 𝑟 𝑃

𝑎 = 𝑡 + Φ′ −Φ

= 2 + 𝑟′ 𝑋 + 𝑟′ 𝑃 + 𝑟′ 𝐺 − 𝑟 𝑋 − 𝑟 𝑃− 𝑟 𝐺≤ 2 + 𝑟′ 𝑋 + 𝑟′ 𝐺 − 2𝑟 𝑋

Page 193: Spaceships 解説

193 / 277

アクセス補題の証明 (2) “zigzig”-step の場合

2 + 𝑟′ 𝑋 + 𝑟′ 𝐺 − 2𝑟 𝑋 ≤ 3𝑟′ 𝑋 − 3𝑟 𝑋

理由: 𝑟′ 𝐺 + 𝑟 𝑋 − 2𝑟′ 𝑋 ≤ −2 を示したい。

ところで左辺はlog2𝑠′ 𝐺

𝑠′ 𝑋+ log2

𝑠 𝑋

𝑠′ 𝑋 であり、

log2 𝑥が上に凸で、𝑠′ 𝐺 + 𝑠 𝑋 ≤ 𝑠′(𝑋)なのでこの

値は高々−2

よって不等式は示された。

Page 194: Spaceships 解説

194 / 277

アクセス補題の証明 (3) “zigzag”-step の場合

𝑟′ 𝑋 = 𝑟 𝐺 , 𝑟 𝑋 ≤ 𝑟 𝑃

𝑠′ 𝑃 + 𝑠′ 𝐺 ≤ 𝑠′ 𝑋

X

C

P

A

B

G

D X

G

B A

P

C D

Page 195: Spaceships 解説

195 / 277

アクセス補題の証明 (3) “zigzag”-step の場合

以下(2)と同様

Page 196: Spaceships 解説

196 / 277

以上より、Splay操作がならし計算量で𝑂(log𝑁)であることがわかった。

ところで、Splay操作のポテンシャルは高々

𝑂(𝑁 log𝑁 )なので、全体で𝑂((𝑄 + 𝑁) log𝑁)でクエリを処理できることがわかった。

Page 197: Spaceships 解説

197 / 277

以上より、Splay操作がならし計算量で𝑂(log𝑁)であることがわかった。

ところで、Splay操作のポテンシャルは高々

𝑂(𝑁 log𝑁 )なので、全体で𝑂((𝑄 + 𝑁) log𝑁)でクエリを処理できることがわかった。

以上、満点解法その1

Page 198: Spaceships 解説

198 / 277

満点解法その2 - Link/Cut木

Page 199: Spaceships 解説

199 / 277

満点解法その2 - Link/Cut木

Link/Cut木 ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjanが考案したもの

Page 200: Spaceships 解説

200 / 277

満点解法その2 - Link/Cut木

Link/Cut木 ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjanが考案したもの

◦ この問題のために必要な実装は、それよりもはるかに容易

Page 201: Spaceships 解説

201 / 277

満点解法その2 - Link/Cut木

Link/Cut木 ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjanが考案したもの

◦ この問題のために必要な実装は、それよりもはるかに容易 →Link/Cut木の練習としても適している

Page 202: Spaceships 解説

202 / 277

満点解法その2 - Link/Cut木

Link/Cut木 ◦ 元々、フローアルゴリズムの高速化のためにSleatorとTarjanが考案したもの

◦ この問題のために必要な実装は、それよりもはるかに容易 →Link/Cut木の練習としても適している

◦ いろいろなバージョンがあるが、Splay木によるものが使いやすい

Page 203: Spaceships 解説

203 / 277

予備知識 – Heavy/Light decomposition

Page 204: Spaceships 解説

204 / 277

予備知識 – Heavy/Light decomposition ◦ 木をパスに分割する方法

B

D E

A

C

F

Page 205: Spaceships 解説

205 / 277

予備知識 – Heavy/Light decomposition ◦ 木をパスに分割する方法

B

D E

A

C

F

Page 206: Spaceships 解説

206 / 277

予備知識 – Heavy/Light decomposition ◦ 木をパスに分割する方法

変な形の木でも、「パスの木」の形に潰すと安定する

Page 207: Spaceships 解説

207 / 277

Splay Treeの世界

列データ

Splay Tree

列の畳み込みを効率よく計算

Page 208: Spaceships 解説

208 / 277

Splay Treeの世界

列データ

Splay Tree

列の畳み込みを効率よく計算

Page 209: Spaceships 解説

209 / 277

Heavy/Light decompositionの世界

列データ

有向木を分解したもの

有向木

Splay Tree

列の畳み込みを効率よく計算

Page 210: Spaceships 解説

210 / 277

Link/Cut Treeの世界

列データ

有向木を分解したもの

Splay Tree

列の畳み込みを効率よく計算

有向木

Link/Cut Tree

パスの畳み込みを効率よく計算

Page 211: Spaceships 解説

211 / 277

Link/Cut Treeの世界

H/L分解 = パスからなる木

Page 212: Spaceships 解説

212 / 277

Link/Cut Treeの世界

H/L分解 = パスからなる木

Link/Cut Tree = Splay木からなる木

Page 213: Spaceships 解説

213 / 277

Link/Cut Tree の辺は二種類ある ◦ Solid(Heavy) edge

◦ Dashed(Light) edge

Page 214: Spaceships 解説

214 / 277

Link/Cut Tree の辺は二種類ある

Solid(Heavy) Dashed(Light)

所属 Splay Tree H/L分解の木

分類 二分木 多分木

左右の区別 左右の区別あり なし

親 本当は祖先か子孫 本当の親

子供 本当は祖先か子孫 本当は子孫

Page 215: Spaceships 解説

215 / 277

Solid, Dashedの区別

Page 216: Spaceships 解説

216 / 277

Solid, Dashedの区別

いずれも、親方向リンクを持つ

X

R L

M

Page 217: Spaceships 解説

217 / 277

Solid, Dashedの区別

いずれも、親方向リンクを持つ

親から左方向リンクがあれば、Solid

X

R L

M

Page 218: Spaceships 解説

218 / 277

Solid, Dashedの区別

いずれも、親方向リンクを持つ

親から左方向リンクがあれば、Solid

親から右方向リンクがあれば、Solid

X

R L

M

Page 219: Spaceships 解説

219 / 277

Solid, Dashedの区別

いずれも、親方向リンクを持つ

親から左方向リンクがあれば、Solid

親から右方向リンクがあれば、Solid

どちらもなければ、Dashed

X

R L

M

Page 220: Spaceships 解説

220 / 277

Solid, Dashedの区別

いずれも、親方向リンクを持つ

親から左方向リンクがあれば、Solid

親から右方向リンクがあれば、Solid

どちらもなければ、Dashed

「右, 左, 親」の3つのリンクだけで構造を保持できる!

Page 221: Spaceships 解説

221 / 277

小さな例

C

E D

B

F

A

Page 222: Spaceships 解説

222 / 277

小さな例

C

E D

B

F

A

Page 223: Spaceships 解説

223 / 277

小さな例

C

E

D

B F A

C

E D

B

F

A

Page 224: Spaceships 解説

224 / 277

小さな例

C

E

D

B

F A

C

E D

B

F

A

C

E

D

B F A

Page 225: Spaceships 解説

225 / 277

Link/Cut Treeの操作: splayLC()

Link/Cut Tree上では、任意の頂点Xを根に持っていくことができる ◦ 元の木の構造は変化しないことに注意

Page 226: Spaceships 解説

226 / 277

前準備: splay

各Splay Tree上でsplayをすることで、Xから今の根までを点線だけで行けるようにする

Page 227: Spaceships 解説

227 / 277

前準備: splay

各Splay Tree上でsplayをすることで、Xから今の根までを点線だけで行けるようにする

C

E

D

B

F A

Page 228: Spaceships 解説

228 / 277

前準備: splay

各Splay Tree上でsplayをすることで、Xから今の根までを点線だけで行けるようにする

C

E

D

B

F A

Page 229: Spaceships 解説

229 / 277

前準備: splay

各Splay Tree上でsplayをすることで、Xから今の根までを点線だけで行けるようにする

C

E

D

B

F A

EからBまで、点

線のみで行けるようになる

Page 230: Spaceships 解説

230 / 277

splayLC() のメイン操作: つなぎ変え(expose操作)

パスのつなぎ変え操作を行う

元の木ではこんな感じ

Page 231: Spaceships 解説

231 / 277

splayLC() のメイン操作: つなぎ変え(expose操作)

パスのつなぎ変え操作を行う

元の木ではこんな感じ

C

E D

B

F

A

Page 232: Spaceships 解説

232 / 277

splayLC() のメイン操作: つなぎ変え(expose操作)

パスのつなぎ変え操作を行う

元の木ではこんな感じ

C

E D

B

F

A

Page 233: Spaceships 解説

233 / 277

splayLC() のメイン操作: つなぎ変え(expose操作)

パスのつなぎ変え操作を行う

元の木ではこんな感じ

C

E D

B

F

A

Page 234: Spaceships 解説

234 / 277

splayLC() のメイン操作: つなぎ変え(expose操作)

パスのつなぎ変え操作を行う

Link/Cut 木でも、左向きのSolid辺を付け替えるだけ

Page 235: Spaceships 解説

235 / 277

splayLC() のメイン操作: つなぎ変え(expose操作)

パスのつなぎ変え操作を行う

Link/Cut 木でも、左向きのSolid辺を付け替えるだけ

C

E

D

B

F A

Page 236: Spaceships 解説

236 / 277

splayLC() のメイン操作: つなぎ変え(expose操作)

パスのつなぎ変え操作を行う

Link/Cut 木でも、左向きのSolid辺を付け替えるだけ

C

E

D

B

F A

Page 237: Spaceships 解説

237 / 277

splayLC() のメイン操作: つなぎ変え(expose操作)

パスのつなぎ変え操作を行う

Link/Cut 木でも、左向きのSolid辺を付け替えるだけ

C

E

D

B

F

A

Page 238: Spaceships 解説

238 / 277

左向きの辺をつなぎ替えるだけで、Eが一番上の木に所属するようになった

Page 239: Spaceships 解説

239 / 277

左向きの辺をつなぎ替えるだけで、Eが一番上の木に所属するようになった

最後にもう1度splay()操作を行うことで、Link/Cut Treeの一番上の根にEが来る

Page 240: Spaceships 解説

240 / 277

L/C木のsplayLC()はSplay Treeの解析を少し応用すると、対数時間であることが言える

Page 241: Spaceships 解説

241 / 277

L/C木のsplayLC()はSplay Treeの解析を少し応用すると、対数時間であることが言える

1回ごとのsplay()操作が対数時間であることは既にわかっている

Page 242: Spaceships 解説

242 / 277

L/C木のsplayLC()はSplay Treeの解析を少し応用すると、対数時間であることが言える

1回ごとのsplay()操作が対数時間であることは既にわかっている

しかし実際にはsplay()操作が𝑘回呼ばれている ◦ 𝑘は、パス分割された木の上での深さ

Page 243: Spaceships 解説

243 / 277

ポテンシャルの定義 ◦ サイズ = solid/dashedに関わらず、子孫になっている頂点の数

◦ ランク = その対数

◦ ポテンシャル = ランクの総和の2倍 として定める

Page 244: Spaceships 解説

244 / 277

Splay Treeのならし計算量は 1 + 3𝑟 𝑡 − 3𝑟(𝑥) だった

今回のならし計算量は𝑘 + 6𝑟 𝑡 − 6𝑟(𝑥)になる ◦ 「Splayが𝑘回呼ばれる」という認識を改めてみる

◦ Splayは根に向かって順番に呼ばれるということを考慮すると、 「Splayが1回呼ばれるが、途中でk回、強制的にzigステップを使われるかもしれない」と考えることができる

◦ 係数が2倍なのはポテンシャルの定義を変えたから

Page 245: Spaceships 解説

245 / 277

余った定数項𝑘の回収

Expose操作のあとに1回行うsplay操作: k回の回転を行う。

ポテンシャルの定義を2倍にしたので、splayの回転操作1回につき1の追加コストを課しても問題ない

Page 246: Spaceships 解説

246 / 277

ならしコスト6 log2𝑁のsplay操作を2回呼んでいるので、splayLC()のならし計算量は12 log2𝑁 = 𝑂(log𝑁) であるとわかった。

Page 247: Spaceships 解説

247 / 277

AとBのLCAを求める。

Page 248: Spaceships 解説

248 / 277

AとBのLCAを求めるには、まず 1. Bに対してsplayLC()を行う

2. Aに対してsplayLC()を行う

このとき、Bは浅い位置にいる。 ◦ Splay Treeに対するSplay操作1回で、他の頂点の深さは高々

2段しか下がらないので、この時点でBは深さ高々4程度。

Page 249: Spaceships 解説

249 / 277

AとBの位置関係に基いて条件分岐

Page 250: Spaceships 解説

250 / 277

AとBの位置関係に基いて条件分岐

(1) BがAの左側にある場合 ◦ この場合は、BはAの子孫ということになるので、AとBのLCAはAになる。

(2) BがAの右側にある場合 ◦ 次のページへ

Page 251: Spaceships 解説

251 / 277

BがAの右側にある場合の条件分岐

(1) BがAと同じSplay Treeに属する場合 ◦ この場合は、AはBの子孫ということになるので、AとBのLCAはBになる。

Page 252: Spaceships 解説

252 / 277

BがAの右側にある場合の条件分岐

(1) BがAと同じSplay Treeに属する場合 ◦ この場合は、AはBの子孫ということになるので、AとBのLCAはBになる。

(2) BがAと異なるSplay Treeに属する場合 ◦ 一番一般的な場合。

◦ Bから上に辿り、Aと同じSplay Treeに到達したところの頂点が、AとBのLCAになる。

Page 253: Spaceships 解説

253 / 277

BがAの右側にある場合の条件分岐

(1) BがAと同じSplay Treeに属する場合 ◦ この場合は、AはBの子孫ということになるので、AとBのLCAはBになる。

(2) BがAと異なるSplay Treeに属する場合 ◦ 一番一般的な場合。

◦ Bから上に辿り、Aと同じSplay Treeに到達したところの頂点が、AとBのLCAになる。

これでLCAは求められた。

Page 254: Spaceships 解説

254 / 277

クエリ1,2番に対応する「接続」「切断」は、 Link/Cut Treeの”link”, “cut” に対応する。

Page 255: Spaceships 解説

255 / 277

クエリ1,2番に対応する「接続」「切断」は、 Link/Cut Treeの”link”, “cut” に対応する。

(1) Link操作 – AをBの子にする ◦ AとBをsplayLC()しておいてから、Aの親として(dashedで)Bを設定するだけ。

◦ 計算量: AとBがLink/Cut Treeにおける根にあるので、Bのサイズが高々𝑁増える程度。これによってポテンシャルは𝑂(log𝑁) しか増えない。

Page 256: Spaceships 解説

256 / 277

クエリ1,2番に対応する「接続」「切断」は、 Link/Cut Treeの”link”, “cut” に対応する。

(2) Cut操作 – Aを親から切り離す ◦ AをsplayLC()してからAの右の子を切り離す。

◦ 計算量:ポテンシャルは明らかに減っている。

Page 257: Spaceships 解説

257 / 277

以上がLink/Cut Treeによる満点解法。

Page 258: Spaceships 解説

258 / 277

Euler Tour Tree と Link/Cut Tree は動的木の筆頭

Page 259: Spaceships 解説

259 / 277

Euler Tour Tree と Link/Cut Tree は動的木の筆頭

今回はどちらを選ぶべきだったか?

Page 260: Spaceships 解説

260 / 277

Euler Tour Tree と Link/Cut Tree は動的木の筆頭

今回はどちらを選ぶべきだったか?

(他の問題は解き終わっているとして)

Page 261: Spaceships 解説

261 / 277

Euler Tour Tree ◦ 知識:

◦ 実装:

Link/Cut Tree ◦ 知識:

◦ 実装:

Page 262: Spaceships 解説

262 / 277

Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。

◦ 実装:

Link/Cut Tree ◦ 知識:

◦ 実装:

Page 263: Spaceships 解説

263 / 277

Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。

◦ 実装: 組み合わせてはいけないものを組み合わせてしまった感じ

Link/Cut Tree ◦ 知識:

◦ 実装:

Page 264: Spaceships 解説

264 / 277

Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。

◦ 実装: 組み合わせてはいけないものを組み合わせてしまった感じ

Link/Cut Tree ◦ 知識: 必須

◦ 実装:

Page 265: Spaceships 解説

265 / 277

Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。

◦ 実装: 組み合わせてはいけないものを組み合わせてしまった感じ

Link/Cut Tree ◦ 知識: 必須

◦ 実装: 頂点にデータを持たせなくてよいなど、この問題においては極めて有利

Page 266: Spaceships 解説

266 / 277

Euler Tour Tree ◦ 知識: 過去にも出題済みの知識の組合せ。 ◦ 実装: 組み合わせてはいけないものを組み合わせてしまった感じ

Link/Cut Tree ◦ 知識: 必須 ◦ 実装: 頂点にデータを持たせなくてよいなど、この問題においては極めて有利

知っているならLink/Cut を書くべきだったかもしれない

Page 267: Spaceships 解説

267 / 277

Link/Cutを学ぶべきか?

Page 268: Spaceships 解説

268 / 277

Link/Cutを学ぶべきか? ◦ Link/Cutでなければ出来ない、という問題は、恐らくない

Page 269: Spaceships 解説

269 / 277

Link/Cutを学ぶべきか? ◦ Link/Cutでなければ出来ない、という問題は、恐らくない

◦ しかし、Link/Cutを使うと有利な問題は実際に存在している

Page 270: Spaceships 解説

270 / 277

qnighyからの提案

Page 271: Spaceships 解説

271 / 277

qnighyからの提案 ◦ 合宿参加者の大半にとっては、Link/Cut Treeを習得するコストが高くつく上に、他の学習をしたほうがずっと為になると思う。

Page 272: Spaceships 解説

272 / 277

qnighyからの提案 ◦ 合宿参加者の大半にとっては、Link/Cut Treeを習得するコストが高くつく上に、他の学習をしたほうがずっと為になると思う。

◦ より上位の人や、単純に興味があるという人に関しては、この限りではない。

Page 273: Spaceships 解説

273 / 277

qnighyからの提案 ◦ 合宿参加者の大半にとっては、Link/Cut Treeを習得するコストが高くつく上に、他の学習をしたほうがずっと為になると思う。

◦ より上位の人や、単純に興味があるという人に関しては、この限りではない。

◦ いずれにせよ、学習するつもりなら、身に付けるために問題を解くべきだろう。

Page 274: Spaceships 解説

274 / 277

JOI2010春合宿 Day4 “Highway”

JOI2012本選 問題5 “Festivals in JOI Kingdom”

IOI2011 Day2 “Elephants”

IJPC2012 Day3 “Animals2”

Page 275: Spaceships 解説

275 / 277

完全制覇・ツリー上でのクエリ処理技法 [iwiwi] http://topcoder.g.hatena.ne.jp/iwiwi/20111205/1323099376

プログラミングコンテストでのデータ構造 2 ~動的木編~ [iwiwi] http://www.slideshare.net/iwiwi/2-12188845

蟻本 [iwiwi]

Page 276: Spaceships 解説

276 / 277

Daniel D. Sleator and Robert E. Tarjan, A Data Structure for Dynamic Trees, Journal of Computer and System Sciences, Volume 26 Issue 3, June 1983, pp. 362 – 391

Daniel D. Sleator and Robert E. Tarjan, Self-adjusting binary search trees, Journal of the ACM, Volume 32 Issue 3, July 1985, pp. 652 – 686

Page 277: Spaceships 解説

277 / 277

0

2

4

6

8

10

12

0 10 20 30 40 50 60 70 80 90 100