JOI2015-sp-day4-walls-anothersolution

 JOI2015-sp-day4-walls-anothersolution

第14回情報オリンピック春合宿day4 Walls 別解

65bd3434deeeb8afc00485cdfc3e260a?s=128

snuke

May 02, 2015
Tweet

Transcript

  1. 第14回情報オリンピック  春合宿  day4   Walls  別解解説 ⼆二階堂建⼈人(snuke)

  2. ⼩小課題2 最初、防壁の左端が全部  0

  3. 下ごしらえ 壁を⻑⾧長さでソートしておく

  4. 下ごしらえ どの時点でも⼭山型になっている   (凹んでいたりしない)

  5. レーザー レーザーが来た時は、   ・上  n  個を左揃え   ・上  n  個を右揃え

      のどちらかが起こる
  6. レーザー レーザーが来た時は、   ・上  n  個を左揃え   ・上  n  個を右揃え

      のどちらかが起こる
  7. レーザー レーザーが来た時は、   ・上  n  個を左揃え   ・上  n  個を右揃え

      のどちらかが起こる
  8. segtree segtreeを作ってみる   ノードに持たせる値は何にするか      

     
  9. ノードに持たせる値 とりあえず、state,pos  を⽤用意する   ・state  =  1  なら、区間内の防壁がposで左揃えされている   ・state

     =  2  なら、区間内の防壁がposで右揃えされている   ・state  =  -‐‑‒1  なら、区間は揃っていない (state,pos)  =  (-‐‑‒1,-‐‑‒1) 2,10 -‐‑‒1,-‐‑‒1 2,10 2,10 -‐‑‒1,-‐‑‒1 1,0 2,10 2,10 2,10 2,10 1,4 1,2 1,0 1,0
  10. 更更新⽅方法 state  =  1  の場合(区間が全てposで左揃え)   ・区間が全てpi で左揃えされる場合:普通に更更新   ・区間が全てpi

    で右揃えされる場合:普通に更更新   ・区間が揃わない場合:
     stateを  -‐‑‒1  にして、左の⼦子に潜り、       ・左の⼦子が揃わなかった場合:右の⼦子には潜らない       ・左の⼦子が揃った場合:右の⼦子にも潜る   (state  =  2  の場合(区間が全てposで右揃え)も同様) =state,posの組が同じ
  11. 更更新⽅方法 state  =  -‐‑‒1  の場合(区間が揃っていない)   ・左の⼦子に潜る     ・左の⼦子が揃わなかった場合:右の⼦子には潜らない  

      ・左の⼦子が揃った場合:右の⼦子にも潜る   ・潜った後、
   ・左右の⼦子が揃った場合:state,posを⼦子と同じにする     ・左右の⼦子が揃わなかった場合:stateを-‐‑‒1にする
  12. 更更新⽅方法 state  =  1  の場合(区間が全てposで左揃え)   ・区間が全てpi で左揃えされる場合:普通に更更新   ・区間が全てpi

    で右揃えされる場合:普通に更更新   ・区間が揃わない場合:
     stateを  -‐‑‒1  にして、左の⼦子に潜り、       ・左の⼦子が揃わなかった場合:右の⼦子には潜らない       ・左の⼦子が揃った場合:右の⼦子にも潜る   →  ノードに  w  =「区間内の防壁の⻑⾧長さの最⼤大」も
     持たせておくとよい(⻑⾧長いのが揃えば短いのも揃う)
  13. 答えを求める 答えを求めるためには、   各ノードになにを持たせればいいか  

  14. 各移動の⻑⾧長さ 左揃え  →  左揃え(右揃え  →  右揃え)   p 移動量量:pos  -‐‑‒

     p pos wi
  15. 左揃え  →  右揃え(右揃え  →  左揃え)   pos wi 各移動の⻑⾧長さ 移動量量:p

     -‐‑‒  pos  -‐‑‒  wi  +  1 p
  16. 答えを求める ・pos  -‐‑‒  p   ・p  -‐‑‒  pos  -‐‑‒  wi

     +  1   をいくつか⾜足したものが答え   各防壁の答えは、   ・x  +  wi  *  y   という形で表せそう
  17. 答えを求める segtreeの各ノードに、sum,cnt  という値を持たせる   答えは「sumの和  +  cntの和  *  wi 」

      更更新は   ・左揃え→左揃え:sum  +=  pos  -‐‑‒  p   ・左揃え→右揃え:sum  +=  p  -‐‑‒  pos  +  1,  cnt  -‐‑‒=  wi   とすればいい
  18. まとめ segtreeを作り、ノードには以下の値を持たせる   ・state,pos:左揃い・右揃い・不不揃い、揃った場所   ・w:防壁の最⼤大⻑⾧長区間(全て揃うかを判定するため)   ・sum,cnt:答えを計算するための値   更更新は、

      ・state,posを更更新するついでにsum,cntを更更新する   ・state=1,2(揃っている)なら普通に更更新   ・state=-‐‑‒1(不不揃い)なら⼦子に潜る   →  計算量量は?
  19. 計算量量 state  =  -‐‑‒1  の場合(区間が揃っていない)   ・左の⼦子に潜る     ・左の⼦子が揃わなかった場合:右の⼦子には潜らない  

      ・左の⼦子が揃った場合:右の⼦子にも潜る   ・潜った後、
   ・左右の⼦子が揃った場合:state,posを⼦子と同じにする     ・左右の⼦子が揃わなかった場合:stateを-‐‑‒1にする state  =  1  の場合(区間が全てposで左揃え)   ・区間が全てp i で左揃えされる場合:普通に更更新   ・区間が全てp i で右揃えされる場合:普通に更更新   ・区間が揃わない場合:
     stateを  -‐‑‒1  にして、左の⼦子に潜り、       ・左の⼦子が揃わなかった場合:右の⼦子には潜らない       ・左の⼦子が揃った場合:右の⼦子にも潜る   (state  =  2  の場合(区間が全てposで右揃え)も同様) ポイント   ・state  =  -‐‑‒1  なら潜る   ・stateによらず、まず左の⼦子に潜り、     ・左の⼦子が揃わなかった場合:右の⼦子には潜らない     ・左の⼦子が揃った場合:右の⼦子にも潜る
  20. 計算量量 ⾚赤い線のようにsegtree上を動きます   たくさんのノードを辿ることもありそうに⾒見見えます  

  21. 計算量量 ◯で囲ったような部分、   つまり左も右もがっつり潜る部分の個数を  x  とすると、   O(x  *  segtreeの⾼高さ(=logN))

     で抑えられそうです   ※ここのように、潜った直後に帰ってくる場所は含まない  
  22. 計算量量 ・◯で囲ったような部分のstateは  -‐‑‒1  のはず  

  23. 計算量量 ・右の⼦子にも潜るということは、左の⼦子は全部揃っている   →  ◯の部分で右に潜ったということは、       △のstateが  -‐‑‒1  から

     1  か  2  になる  
  24. 計算量量 つまり左も右もがっつり潜る部分の個数を  x  とすると、   O(x  *  segtreeの⾼高さ=(logN))  で抑えられそうです  

    ・潜るノードの個数が  O(log  N)  回増えるときは、     state=-‐‑‒1  のノードが  1  つ減る!   ・さらに、stateが  1  か  2  から  -‐‑‒1  になるノードは、1つの
   レーザーにつき、O(log  N)  個     →  そのような場所は、
       i  =  iより左は全部揃い、iより右は揃わない
     というような  i  を含む区間のみ
  25. 計算量量 ・潜るノードの個数が  O(log  N)  回増えるときは、     必ず  state=-‐‑‒1  のノードが  1

     つ減る!   ・さらに、stateが  1  か  2  から  -‐‑‒1  になるノードは、1つの
   レーザーにつき、O(log  N)  個   潜るノードの個数が増える回数  ≦  state=-‐‑‒1のノードが減る個数   state=-‐‑‒1のノードが減る個数  ≦  state=-‐‑‒1のノードが増える個数   state=-‐‑‒1のノードが増える個数  ≦  O(log  N)*レーザーの個数   つまり、   潜るノードの個数が増える回数  ≦  O(log  N)*レーザーの個数!   →  ならし計算量量が  O(log^2  N)  になった!
  26. ⼩小課題2 このように、   保留留した頂点を後で潜る、遅延更更新の発展系のような⼿手法   を使うと、O(M  log^2  N)  で解けた!  

    参考   http://snuke.hatenablog.com/entry/2014/08/02/202210
  27. ⼩小課題3 初期位置がめちゃくちゃなので、そのままだとダメ   初期位置が  0  だったときとの差分を計算してやると良良い