1223D. Sequence Sorting(DP)
題目鏈接:傳送門
思路:
我們假設序列,序列。
即序列D是沒有移動的數,序列M是向左移動或向右移動的數,我們設 和 分別是數 在序列 中出現的最大位置下標和最小位置下標。那麼序列D和序列M必定滿足下列條件
- 對於,假設,那麼。(原因:這樣序列纔能有序且不移動)
- 對於序列M中的任意一個數,滿足 不夾在序列D的最大和最小值之間,即或成立,即數列D中相鄰的兩個元素在排序上也是相鄰的(原因:因爲序列M中的數字向左或向右移動,那麼其必定移動到序列D的兩側,又因爲最終序列是有序的,則滿足上述條件)
因爲序列M的長度加序列D的長度之和爲元素的種類數,我們現在只需求出序列D最長爲多長即可。
我們用表示序列D中最後一個數是排名爲 的數的最大長度,
- 如果,排名爲 的最小出現位置小於排名爲 的最大出現位置,
- 否則
代碼:
#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=3e5+10;
int minp[N],maxp[N];
vector<int> v;
int dp[N];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)
minp[i]=-1;
v.clear();
for(int i=1;i<=n;++i)
{
int x;
scanf("%d",&x);
v.push_back(x);
if(minp[x]==-1) minp[x]=i;
maxp[x]=i;
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
int ans=n;
for(int i=0;i<int(v.size());++i)
{
if(i==0||minp[v[i]]<maxp[v[i-1]]) dp[i]=1;
else dp[i]=dp[i-1]+1;
ans=min(ans,int(v.size())-dp[i]);
}
printf("%d\n",ans);
}
// for()
return 0;
}