1. 程式人生 > 實用技巧 >牛客多校(2020第五場)D Drop Voicing

牛客多校(2020第五場)D Drop Voicing

題目連結: https://ac.nowcoder.com/acm/contest/5670/D

題意:

  • 給定一個1~n得排列,有倆種操作
  • 操作1:可以將倒數第二個數放到開頭
  • 操作2:可以將開頭得第一個數放到最後
  • 連續若干次操作1(包括1次)成為一段
  • 現在要將排序變成1~n,要使得段數儘可能最小,輸出這個最小值
  • 2 <= n <= 500

題解:

  

  通過觀察可以發現,我們只需要取環得最長上升子序列,然後用n - 最長上升子序列

  

 1 /* 
 2 求最大上升子序列
 3  */
 4 #include<iostream>
 5 #include<algorithm>
 6
#include<cstring> 7 8 using namespace std; 9 #define INF 0x3f3f3f3f 10 const int N = 505*2; 11 12 int a[N]; 13 int n; 14 15 int LIS(int l, int r) { 16 int dp[N]; 17 fill(dp, dp+N, INF); 18 for (int i = l; i <= r; i++) { 19 *lower_bound(dp+1, dp+n+1, a[i]) = a[i]; 20 }
21 int len = lower_bound(dp+1, dp+n+1, INF) - dp - 1; 22 return len; 23 } 24 25 int main() { 26 scanf("%d", &n); 27 for (int i = 1; i <= n; i++) { 28 scanf("%d", &a[i]); 29 a[i+n] = a[i]; 30 } 31 32 int ans = 0; 33 for (int i = 1; i <= n; i++) {
34 ans = max(ans, LIS(i, i+n-1)); 35 } 36 printf("%d\n", n - ans); 37 }

參考:https://blog.csdn.net/qq_49528097/article/details/107583809