rupc2017:g解説

34
Problem G: Chairs : aoba : がっちょ1 / 34

Upload: takumi-yamashita

Post on 05-Apr-2017

17 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: RUPC2017:G解説

Problem G: Chairs

作問: aoba解説: がっちょ君

1 / 34

Page 2: RUPC2017:G解説

問題概要- 番号1∼NのN個の椅子がある

- ID1∼NのN人がいて、人iは椅子piに座りたい

- 人々はIDが小さい順に1列に並び、列が前の人から以下の操作を行う

1. 椅子piが空席の場合はその席に座る2. 空席ではない場合はpiに1加算して、列の最後尾に並び直す(Nを超えた場合は1となる)

- 全ての人が座るまでこの操作を繰り返す

- 最終的にそれぞれの椅子に座っている人のIDを出力する

- 制約: 1 ≤ N ≤ 105, 1 ≤ pi ≤ N

2 / 34

Page 3: RUPC2017:G解説

ダメな解法

• 問題文通りにシミュレーション

→ 例えば、全ての初期位置が同じ場合はN × (N + 1)/2回の操作をすることになりN = 105なので間に合わない

3 / 34

Page 4: RUPC2017:G解説

ポイント

• 問題を「各椅子に対して人が並んでいる」と置き換える

4 / 34

Page 5: RUPC2017:G解説

解法1

• 累積和 + スタック

5 / 34

Page 6: RUPC2017:G解説

解法1• 問題を置き換えた場合でもどこからどのような順序で処理を行うかを決める必要がある(円環するため)

• 適切な位置を選択することで円環を直線と考えることができる

• 適切な位置は次のように決められる

1. 各椅子に対して初期値を-1として、人が並んでいる場合はその人数だけ加算して累積和を取る

2. その中で最も値が小さい場所をxとすると、x + 1が適切な位置となる(x = Nなら1)

6 / 34

Page 7: RUPC2017:G解説

解法1

• 適切な位置を選んだらその位置からスタックを使い、それぞれの椅子に誰が座るかを決定していく

• O(N)で解くことができる

※ 工夫すると累積和を使用しなくても解くことができる

7 / 34

Page 8: RUPC2017:G解説

解法1

8 / 34

N = 8, p = {1, 5, 1, 7, 4, 5, 7, 5}の場合

1 2 3 4 5 6 7 8

1©3©

5© 2©6©8©

4©7©

1 -1 -1 0 2 -1 1 -1

Page 9: RUPC2017:G解説

解法1

9 / 34

累積和を取る

1 2 3 4 5 6 7 8

1©3©

5© 2©6©8©

4©7©

1 0 -1 -1 1 0 1 0

Page 10: RUPC2017:G解説

解法1

10 / 34

椅子3が最小 → 椅子4から操作を開始する

1 2 3 4 5 6 7 8

1©3©

5© 2©6©8©

4©7©

1 0 -1 -1 1 0 1 0

start→

Page 11: RUPC2017:G解説

解法1

11 / 34

1 2 3 4 5 6 7 8

1©3©

5© 2©6©8©

4©7©

Stack

Page 12: RUPC2017:G解説

解法1

12 / 34

1 2 3 4 5 6 7 8

1©3©

2©6©8©

4©7©

5©Stack

Page 13: RUPC2017:G解説

解法1

13 / 34

1 2 3

5©4 5 6 7 8

1©3©

2©6©8©

4©7©

Stack

Page 14: RUPC2017:G解説

解法1

14 / 34

1 2 3

5©4 5 6 7 8

1©3©

2©6©8©

4©7©

Stack

Page 15: RUPC2017:G解説

解法1

15 / 34

1 2 3

5©4 5 6 7 8

1©3©

4©7©

2©6©8©

Stack

Page 16: RUPC2017:G解説

解法1

16 / 34

1 2 3

5©4

2©5 6 7 8

1©3©

4©7©

6©8©

Stack

Page 17: RUPC2017:G解説

解法1

17 / 34

1 2 3

5©4

2©5 6 7 8

1©3©

4©7©

6©8©

Stack

Page 18: RUPC2017:G解説

解法1

18 / 34

1 2 3

5©4

2©5

6©6 7 8

1©3©

4©7©

8©Stack

Page 19: RUPC2017:G解説

解法1

19 / 34

1 2 3

5©4

2©5

6©6 7 8

1©3©

4©7©

8©Stack

Page 20: RUPC2017:G解説

解法1

20 / 34

1 2 3

5©4

2©5

6©6 7 8

1©3©

4©7©8©

Stack

Page 21: RUPC2017:G解説

解法1

21 / 34

1 2 3

5©4

2©5

6©6

4©7 8

1©3©

7©8©

Stack

Page 22: RUPC2017:G解説

解法1

22 / 34

1 2 3

5©4

2©5

6©6

4©7 8

1©3©

7©8©

Stack

Page 23: RUPC2017:G解説

解法1

23 / 34

1 2 3

5©4

2©5

6©6

4©7

7©8

1©3©

8©Stack

Page 24: RUPC2017:G解説

解法1

24 / 34

1 2 3

5©4

2©5

6©6

4©7

7©8

1©3©

8©Stack

Page 25: RUPC2017:G解説

解法1

25 / 34

1 2 3

5©4

2©5

6©6

4©7

7©8

1©3©8©

Stack

Page 26: RUPC2017:G解説

解法1

26 / 34

1©1 2 3

5©4

2©5

6©6

4©7

7©8

3©8©

Stack

Page 27: RUPC2017:G解説

解法1

27 / 34

1©1 2 3

5©4

2©5

6©6

4©7

7©8

3©8©

Stack

Page 28: RUPC2017:G解説

解法1

28 / 34

1©1

3©2 3

5©4

2©5

6©6

4©7

7©8

8©Stack

Page 29: RUPC2017:G解説

解法1

29 / 34

1©1

3©2 3

5©4

2©5

6©6

4©7

7©8

8©Stack

Page 30: RUPC2017:G解説

解法1

30 / 34

1©1

3©2

8©3

5©4

2©5

6©6

4©7

7©8

Stack

Page 31: RUPC2017:G解説

解法2

• シミュレーション

• 列ごとにまとめて動かしていく

• 任意の順序で列を動かしてOK

31 / 34

Page 32: RUPC2017:G解説

解法2

• 各列について以下の操作を行う必要がある

1. 最寄りの空席の位置を探す

2. 2つの列をマージする(一方の列をもう一方の列の後ろに挿入する)

• これらは例えばstd::setとstd::listを組み合わせるとO(logN)で実現することができる

• N人についてこの操作を行うとO(NlogN)となる

32 / 34

Page 33: RUPC2017:G解説

結果

• Onsite- First Submission: caffe チーム (113 min)- First Accepted: caffe チーム (113 min)

• Online- First Submission: ei1333 さん (49 min)- First Accepted: caffe チーム (113 min)

• Success Rate (Accepted / Submission)12.00 % (3 / 25)

33 / 34

Page 34: RUPC2017:G解説

ジャッジ解

aoba C++ 57行

arrows C++ 49行

arrows Java 38行

gacho C++ 25行

haji C++ 43行

kawa C++ 17行

kzyKT C++ 20行

sate C++ 36行

uku C++ 66行

34 / 34