2019年12月25日水曜日

ARC 032 - 仕事計画

辞書式順序の条件を無視すればただの区間スケジューリングなので、始点aia_iでソートして逆から貪欲に選んでいけば仕事の数の最大数kkが求まる。この際に得られた仕事の列が開始から

(a1,b1),(a2b2),...,(ak,bk) (a'_1, b'_1), (a'_2 b'_2), ..., (a'_k, b'_k)

となっているとする。このとき、次の性質があることに注目する:

  • k1k-1個の仕事をこなすためには、少なくともa2a'_2までには始めなければならないし、a2a'_2までに始めればk1k-1個の仕事が可能である
  • k2k-2個の仕事をこなすためには、少なくともa3a'_3までには始めなければならないし、a3a'_3までに始めればk2k-2個の仕事が可能である
  • ...
  • 11個の仕事をこなすためには、少なくともaka'_kまでには始めなければならないし、aka'_kまでに始めれば11個の仕事が可能である

これらの性質から、kk個の仕事からなる辞書順最小のスケジュールを構成する方法が従う:

  • 11個目の仕事はa2a'_2までに終わるものならなんでも可能である。このうちインデックスが最小のものを(l1,r1)(l_1, r_1)とする。
  • 22個目の仕事はr1r_1以降に始まってa3a'_3までに終わるものならなんでも可能である。このうちインデックスが最小のものを(l2,r2)(l_2, r_2)とする。
  • ...
  • kk個めの仕事はrk1r_{k-1}以降に始まるものならなんでも可能である。このうちインデックスが最小のものを(lk,rk)(l_k, r_k)とする。

こうして辞書順最小のスケジュール(l1,r1),...,(lk,rk)(l_1, r_1), ..., (l_k, r_k)が得られた……わけだが、実際にこのスケジュールを求める手順がまだ明らかでない。

時間xxに始まってyyに終わる仕事のインデックスをf(x,y)f(x, y)とするとき(複数ある場合、インデックスが最小のもの以外は捨ててよい)、仕事は二次元空間上の点とみなせるので、上の性質をさらに言い換えられる:

  • [0,a2]×[0,a2][0, a'_2] \times [0, a'_2]上にある仕事についてf(x,y)f(x, y)の最小値を求める。(l1,r1)(l_1, r_1)で最小になるとする。
  • [r1,a3]×[r1,a3][r_1, a'_3] \times [r_1, a'_3]上にある仕事についてf(x,y)f(x, y)の最小値を求める。(l2,r2)(l_2, r_2)で最小になるとする。
  • ...
  • [rk1,+]×[rk1,+][r_{k-1}, +\infty] \times [r_{k-1}, +\infty]上にある仕事についてf(x,y)f(x, y)の最小値を求める。(lk,rk)(l_k, r_k)で最小になるとする。

ここまで整理すると、min\minを乗せたrange treeで実行できる手順になっている。計算量はO(Nlog2N){O}(N \log^2 N)


線形で求まるのは、手順を示されれば確かにとなるけどまったくわからなかった。

今出題されたら、もう少し制約が大きくなってlog2\log^2は落ちる気がする。この方針のままでも、2D range tree + fractional cascading + 構築O(N){O}(N)クエリO(1){O}(1)のRMQでlog\logを1つにできそう? でも、そもそも平面走査的になんとかできないのかな。