1. 程式人生 > 實用技巧 >2020牛客暑期多校訓練營(第五場)D題Drop Voicing(dp)

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",n-sum);
}