牛客多校(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

浙公网安备 33010602011771号