2020牛客多校第五场D题Drop Voicing(思维 dp lis)
题目链接:https://ac.nowcoder.com/acm/contest/5670/D
题意:输入一个n个数的序列,你有两种操作,第一种把数组第一个移到最后一个,第二种把数组的倒数第二个移到第一个,连续第二种操作为一次花费(一次花费无论多少次),输出最少费用使序列变为升序,即为[1,2,3,4,5.....n]
题解:第一种操作并不能更换数字之间的顺序,无论怎么样置换,都可以把他看做成一个环。第二种操作我们就可以把一个数字移动,结合第一种操作可以移动到他原来的位置。这样我们就求要移动多少个数字就可以了,移动多少个数字变成升序?那不就是lis,枚举n次第一种操作后的数组,每次计算lis,ans=n-lis;
这里第一种操作,我们用STL种的rotate
rotate(beg,newBeg,end)
将区间[beg,end)内的元素进行旋转,执行后*newBeg成为新的第一元素;
#include <bits/stdc++.h> using namespace std; const int maxn=500+7; typedef long long ll; int a[maxn]; int dp[maxn]; int lis(int n){ int res = 0; for(int i = 0; i < n; i ++){ dp[i] = 1; for(int j = 0; j < i; j ++){ if(a[j] < a[i]){ dp[i] = max(dp[i], dp[j] + 1); } } res = max(res, dp[i]); } return res; } int main(){ int t,n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); } int ans=0; for(int i=0;i<n;i++){ ans=max(ans,lis(n)); rotate(a,a+1,a+n); } printf("%d\n",n-ans); return 0; }