https://codeforces.com/problemset/problem/1367/F2
直接把数字离散后把下标丢进对应值的桶里面,然后如果要选择[l,r]这段区间作为不动的位置,其中[l+1,r-1]这些数字所有位置必须完全选满,然后等于l的可以只取小于l+1的中位置最小的,等于r的可以只取大于r-1中位置最大的。
滑动窗口搞[l+1,r-1],然后l,r的部分lower_bound搞一下
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
int n,m,ans,cas,k,cnt,tot;
int a[maxl],b[maxl],mx[maxl],num[maxl],dp[maxl];
char s[maxl];
bool in[maxl];
vector <int> c[maxl];
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+1+n);
tot=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=tot;i++)
c[i].clear(),num[i]=0;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
c[a[i]].push_back(i);num[a[i]]++;
}
}
inline void mainwork()
{
ans=0;
for(int i=1;i<=tot;i++)
ans=max(ans,num[i]);
int tmp,j,r;
for(int i=1;i<=tot-1;i++)
{
for(int j=0;j<num[i];j++)
{
tmp=j+1;
tmp+=num[i+1]-(lower_bound(c[i+1].begin(),c[i+1].end(),c[i][j])-c[i+1].begin());
ans=max(tmp,ans);
}
}
for(int i=1;i<=tot;i++)
{
tmp=num[i];r=i;
for(j=i+1;j<=tot;j++)
if(c[j][0]<c[j-1][num[j-1]-1])
{
r=j-1;
break;
}
else
r=j,tmp+=num[j];
if(i>1)
tmp+=lower_bound(c[i-1].begin(),c[i-1].end(),c[i][0])-c[i-1].begin();
if(r<tot)
tmp+=num[r+1]-(lower_bound(c[r+1].begin(),c[r+1].end(),c[r][num[r]-1])-c[r+1].begin());
ans=max(tmp,ans);
i=r;
}
}
inline void print()
{
printf("%d\n",n-ans);
}
int main()
{
int t=1;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}