立命合宿2016day3:d問題

13
RUPC2016 2016/03/08 RUPC2016 Day3 D: Complex Oracle 1 原案:井上 解説:井上 問題文:井上 解答:青木・井上

Upload: hcpc-

Post on 20-Jan-2017

214 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

RUPC2016 Day3 D: Complex Oracle

1

原案:井上 解説:井上問題文:井上 解答:青木・井上

Page 2: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

問題概要

• 長さNの順列pが隠されている • 2つの整数 l, r をサーバーに送ると、区間[l, r]のコンプレックス度を教えてくれる • コンプレックス度 := | { (i,j) | pi>pj かつ l≤i<j≤r} |

• 200,000回以内のクエリで隠された順列pを当てろ

• 制約: 1≤N≤100,000

2

Page 3: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

問題概要

• 長さNの順列pが隠されている • 2つの整数 l, r をサーバーに送ると、区間[l, r]のコンプレックス度を教えてくれる • コンプレックス度 := | { (i,j) | pi>pj かつ l≤i<j≤r} | = 転倒数 (=バブルソートの交換回数)

• 200,000回以内のクエリで隠された順列pを当てろ

• 制約: 1≤N≤100,000

3

Page 4: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

解法のアイデア• inv(l,r) = | { (i,j) | pi>pj かつ l≤i<j≤r} | とする

• inv(l,r) - inv(l+1, r) から、lより右にpl より小さい値がいくつあるかわかる → p[l,N] のみの順列での何番目かがわかる

4

6 4 1 3 5 2

1

2

2 3 1

2番目

Page 5: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

TLE解法• p[l,N] のみの順列での何番目かがわかる • 後ろから更新、p[x]がp[x,N]でk番目なら、

• p[x+1,N]で k≤p[y] であるp[y]を1増やす • p[x] = k とする

• クエリN-1回、ナイーブに更新するとO(N2)でTLE

5

? ? ? 2 3 1

2

4

2 3 4 1

2番目 +1 +1

Page 6: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

想定解法• p[l,N] のみの順列での何番目かがわかる • 逆に、前から考えると、まだ使ってない数字でk番目のものを使えばOK • 平衡二分木やセグメントツリーなどを使ってこのクエリをO(logN)で処理して、全体 O(NlogN)

• クエリN-1回

6

4 3 ? ? ? ?

3番目

候補: {1,2,5,6}

4 3 5 ? ? ?

Page 7: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

セグメントツリーを使う方法• セグメントツリーについては蟻本等を参照 • k番目の要素をとるため、区間和を管理する

• k<=sumなら左に降る • 違うなら k = k - sum として右に降る

7

1 0 1 1 0 1 0 0候補: {1,3,4,6}

0121

13

4k=3

Page 8: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

セグメントツリーを使う方法• セグメントツリーについては蟻本等を参照 • k番目の要素をとるため、区間和を管理する

• k<=sumなら左に降る • 違うなら k = k - sum として右に降る

8

1 0 1 1 0 1 0 0候補: {1,3,4,6}

0121

13

4

k=3

Page 9: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

セグメントツリーを使う方法• セグメントツリーについては蟻本等を参照 • k番目の要素をとるため、区間和を管理する

• k<=sumなら左に降る • 違うなら k = k - sum として右に降る

9

1 0 1 1 0 1 0 0候補: {1,3,4,6}

0121

13

4

k=2

Page 10: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

セグメントツリーを使う方法• セグメントツリーについては蟻本等を参照 • k番目の要素をとるため、区間和を管理する

• k<=sumなら左に降る • 違うなら k = k - sum として右に降る

10

1 0 1 1 0 1 0 0候補: {1,3,4,6}

0121

13

4

Page 11: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

想定解法2• p[x,N] のみの順列での何番目かがわかる • 逆方向にも同様のクエリを投げると、p[1,x] での(降順での) 何番目かがわかる • x-1個のうちk個が自分より大きい → 自分はx-k番目

• 左右に自分より小さい要素がそれぞれa,b個 → 自分は全体でa+b+1番目 → p[x] = a+b+1

• クエリ2N-2回、O(N)

11

? ? ? ? ? ?

前から1番目

Page 12: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

ジャッジ解• 青木 (Java, O(N)): 59行 1886B

• 井上 (C++, O(N)): 44行 781B

• 井上 (C++, O(NlogN)): 71行 1308B

12

Page 13: 立命合宿2016Day3:D問題

RUPC2016 2016/03/08

回答状況• Accept / Submit

• 15 / 47 (31.91%)

• First Acceptance

• onsite: popnow (00:56)

• online: rickytheta (00:33)

13