题目链接: 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 - ans); 37 }
参考:https://blog.csdn.net/qq_49528097/article/details/107583809