2020牛客暑期多校训练营(第五场)D题Drop Voicing(dp)
题意:长度为n的一个排列,两种操作,将最前的放到最后,或将最后的前一个放到最前,连续的第二种操作要消耗一费,求变成至小到大的最少费用。
题解:根据本题的规则,很明显可以发现结合两种操作可以将操作变成,将任意一个位置的数插入其他位置需要1费,那么对于一个序列可以固定正确的位置,将每个不正确的位置用费用插入正确的位置既可(正确的位置即从小至大的数),即求最长上升子序列,枚举每一种最长上升子序列既可。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,a[1007],ans,f[1007],sum;
int main(){
scanf("%d",&n);
sum=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i+n]=a[i];
}
for(int i=1;i<=n;i++){
memset(f,0,sizeof(f));
f[1]=a[i];
ans=1;
for(int j=i;j<n+i;j++){
int l=1,r=ans;
while(l<=r){
int mid=(l+r)/2;
if(f[mid]>=a[j]){
r=mid-1;
}
else{
l=mid+1;
}
}
f[l]=a[j];
if(l>ans)ans=l;
}
sum=max(ans,sum);
}
printf("%d
",n-sum);
}