2020牛客暑期多校训练营(第五场)D题Drop Voicing(dp)

2020牛客暑期多校训练营(第五场)D题Drop Voicing(dp)

Drop Voicing

题意:长度为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);
}
原文地址:https://www.cnblogs.com/whitelily/p/13380573.html