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

猜你喜欢

转载自blog.csdn.net/Mrwei_418/article/details/108092092