Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JOI2015-sp-day4-walls-anothersolution

 JOI2015-sp-day4-walls-anothersolution

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

snuke

May 02, 2015
Tweet

More Decks by snuke

Other Decks in Programming

Transcript

  1. ノードに持たせる値 とりあえず、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
  2. 更更新⽅方法 state  =  1  の場合(区間が全てposで左揃え)   ・区間が全てpi で左揃えされる場合:普通に更更新   ・区間が全てpi

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

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

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

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

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

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

      ・左の⼦子が揃った場合:右の⼦子にも潜る   ・潜った後、
   ・左右の⼦子が揃った場合:state,posを⼦子と同じにする     ・左右の⼦子が揃わなかった場合:stateを-‐‑‒1にする state  =  1  の場合(区間が全てposで左揃え)   ・区間が全てp i で左揃えされる場合:普通に更更新   ・区間が全てp i で右揃えされる場合:普通に更更新   ・区間が揃わない場合:
     stateを  -‐‑‒1  にして、左の⼦子に潜り、       ・左の⼦子が揃わなかった場合:右の⼦子には潜らない       ・左の⼦子が揃った場合:右の⼦子にも潜る   (state  =  2  の場合(区間が全てposで右揃え)も同様) ポイント   ・state  =  -‐‑‒1  なら潜る   ・stateによらず、まず左の⼦子に潜り、     ・左の⼦子が揃わなかった場合:右の⼦子には潜らない     ・左の⼦子が揃った場合:右の⼦子にも潜る
  9. 計算量量 ◯で囲ったような部分、   つまり左も右もがっつり潜る部分の個数を  x  とすると、   O(x  *  segtreeの⾼高さ(=logN))

     で抑えられそうです   ※ここのように、潜った直後に帰ってくる場所は含まない  
  10. 計算量量 つまり左も右もがっつり潜る部分の個数を  x  とすると、   O(x  *  segtreeの⾼高さ=(logN))  で抑えられそうです  

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