1. 程式人生 > 其它 >[CF1367F] Flying Sort 題解

[CF1367F] Flying Sort 題解

你谷 link

CF link

題解區都是一些 dp 做法,這裡帶來一種貪心+雙指標的做法。

正片開始

題面不多做贅述,直接講做法。

首先題面等價於選出一個單調遞增的子序列,滿足剩下的所有數要麼比該子序列中最小的數小,要麼比該子序列中最大的數大,求子序列最長長度。

發現這個東西可以 dp,但是其實也可以不 dp,直接貪心也可以。

首先一個性質,就是離散化完後選出的子序列在值域上是連續的,且子序列中出現的數除了左右端點的數,別的數只要在序列中出現了,那麼所有和這個數相等的數都被必須選中了。

所以形如 \(x,x,\cdots,x,x+1,x+1,\cdots,x+1,\cdots,y-1,\cdots,y-1,y,\cdots,y\)

,且所有 \(a\) 滿足 \(a\in[x+1,y-1]\) 都在該子序列中出現了。

利用這個性質,我們可以先將所有值離散化,然後將每個數出現的所有位置都記下來,然後列舉值的右端點的前一個,即上面的 \(y-1\),發現可以貪心地找到最靠前的 \(x+1\),滿足任意 \(a\in[x+1,y-2]\) 滿足 \(r_a<l_{a+1}\),即出現區間無交集。

這個顯然可以雙指標掃一遍得到,然後左右兩邊的 \(x\)\(y\) 直接二分就可以了,其實也可以預處理,即在前面統計每個值出現位置時順便記錄,但二分寫著更方便,且本處也不是時間複雜度瓶頸。

但是這樣還會算漏一部分,就是當解形如 \(x,x,\cdots,x,x+1,\cdots,x+1\)

時,即沒有中間全取的區間,兩邊都取得不完整,這樣也可以做,就是直接列舉中間點,即第一個 \(x+1\) 的位置,然後二分前面 \(x\) 的個數和之後 \(x+1\) 的個數。

這樣時間複雜度就是 \(\mathcal O\left(n\log n\right)\)

接下來就是程式碼