JOI2018 予選 F - L番目のK番目の数
0-based(A0,A1,...,AN−1)で考える。
書き出した数の中にx以下の数がf(x)個あるとするとき、f(x)≥Lとなるような最小のxを求めればよい。この言い換えを元の数列(Ai)の言葉でさらに言い換えると、次のようになる:
x以下の数をK個以上含むような部分列A[l,r)がL個以上存在するようなxの中で最小のものを求めよ。
部分列A[l,r)がx以下の数をg(l,r,x)個含むとする。xを固定した時に、g(l,r,x)≥Kであるようなl,r∈[0,N]が何組あるか数えられれば、二分探索で上のxも求まりそう。具体的には次のように数える:
g(0,i,x)は部分列A[0,i)の中のx以下の数の総数だから、累積和でテーブルを作っておけば任意のiについてO(1)で求まる。そして、g(l,r,x)=g(0,r,x)−g(0,l,x)≥K⇔g(0,r,x)≥K+g(0,l,x)であり、lを固定した時にこの式を満たすようなrの数は二分探索で求まる。したがって、すべてのl∈[0,N]についてこのrの数を求めて足し合わせると、それがf(x)である。
あとはf(x)について二分探索して、f(x)≥Lであるような最小のxを求めればそれが答えになっている。計算量はO(Nlog2N)。