题意
给一个长度为$n$的数组,你可以有两种操作
- 将某一个数放置在数组开头
- 将某一个数放置在数组结尾
问最小操作多少次可以得到一个非递减数列
(比$F1$难在$n$变大,且数组中元素可以有相同的)
分析
因为数组中的数很大,我们可以将其离散化然后操作,则$a[i]$为连续的整数,设$tot$种不同的数,则$1\leq a[i] \leq tot$
每个数最多操作一次,否则第一次可以不操作,那么我们就要找最多的不需要操作的数,如果不需要操作,则元素的位置不变,如果有这么一组不需要操作的数,我们可以发现,中间的数字是不能插进去的,所以这组数是在排序后仍相邻的数,则要找到最长的子序列,这个子序列在排序后仍然相邻,考虑以下几种情况
- 这组数相同,则没有限制
- 这组数中含有两种数,则要形如$i,i,i,i+1,i+1$这种形式,即排序后仍相邻
- 这组数含有三种以上的数,即形如$i,i,i+1,i+2,i+2,i+3$这种形式,那么中间的数($i+1$,$i+2$)一定是被取完了,否则其他的$i+1$或者$i+2$要插进去只能重新排序,与中间数字不能插进去不符,即这几个数并不是相邻,例如$i,i+1,i+2,i+1$这种序列,$i,i+1,i+2$并不满足条件,因为$i+1$并没取完
设$dp[i][0]$为只取相同的数且以$a[i]$为结尾所得到的最长子序列,$dp[i][1]$为$a[i]$还没取完且所得到的以$a[i]$为结尾最长子序列,$dp[i][2]$为$a[i]$取完且以$a[i]$为结尾所得到的最长子序列,我们用$pos[i]$表示数字$i$上次出现的位置,因为离散化了,所以数组可以满足,状态转移方程为($r[a[i]]$表示$a[i]$最后出现的位置,$l[a[i]]$表示$a[i]$最早出现的位置,$num[a[i]]$表示$a[i]$的个数,$pos[a[i]]$表示上一个$a[i]$出现的位置):
1 | dp[i][0] = dp[pos[a[i]]][0] + 1; |
- $dp[i][0]$,方程表示上一个位置的$a[i]$接着取
- $dp[i][1]$,方程表示上一个$a[i]$接着取,或者上一个$a[i]-1$接着取,或者$a[i]-1$已经全部取完后接着取
- $dp[i][2]$,方程表示从最早出现的$a[i]$开始,后面都只取$a[i]$
1 |
|