2020牛客暑期多校训练营(第五场)D.Drop Voicing

2020牛客暑期多校训练营(第五场)D.Drop Voicing

题目链接

题目描述

Inaka composes music. Today’s arrangement includes a chord of nn notes that are pairwise distinct, represented by a permutation p 1 … n p_{1 \dots n} p1n of integers from 1 to n (inclusive) denoting the notes from the lowest to the highest.

Her friend, Miyako, sneaks in and plays a trick by altering the chord with the following two operations:

  • Drop-2: Take out the second highest note and move it to the lowest position, i.e. change the permutation to p n − 1 , p 1 , p 2 , … , p n − 3 , p n − 2 , p n p_{n-1}, p_1, p_2, \dots, p_{n-3}, p_{n-2},p_n pn1,p1,p2,,pn3,pn2,pn.
  • Invert: Take out the lowest note and move it to the highest position, i.e. change the permutation to p 2 , p 3 , … , p n − 1 , p n , p 1 p_2, p_3, \dots, p_{n-1}, p_n, p_1 p2,p3,,pn1,pn,p1.

Any number of consecutive Drop-2 operations is considered a multi-drop. Miyako would like to change the permutation to an ordered permutation, 1 , 2 , … , n 1, 2, \dots, n 1,2,,n, in the fewest number of multi-drops possible. Please help her find the number of multi-drops needed.

输入描述:

The first line contains an integer n ( 2 ≤ n ≤ 500 ) n (2 \leq n \leq 500) n(2n500) — the number of notes.

The second line contains n space-separated integers p 1 , p 2 , … , p n p_1, p_2, \dots, p_n p1,p2,,pn — the original permutation of notes.

The input guarantees each integer from 1 to n (inclusive) appears in the permutation exactly once.

输出描述:

Output one integer — the number of multi-drops required to change the permutation to an ordered one.

示例1

输入

6
2 4 5 1 3 6

输出

2

示例2

输入

8
8 4 7 3 6 2 5 1

输出

5

这题其实是非常简单的 d p dp dp,很多人容易被题目要求迷惑,我们试想,要求一个序列有序,很容易想到最长上升子序列,保持最长的子序列,调整其他位置即可,而我们看向 i n v e r t invert invert 操作,很明显提示你将序列看作一个环,而且细心一点就会发现,用 i n v e r t invert invert 搭配 d r o p drop drop 操作就可以将任意数字移到任意位置,那么题目到这里就很明确了,无非就是求一个环的最长上升子序列,剩下的元素个数就是需要操作的次数了,还有一个小细节,注意看题目数据大小,数据小一般就提示 DP 了,AC代码如下:

#include
using namespace std;
typedef long long ll;
const int N=505;
int n,a[N],dp[N];
int main(){
    int n,ans=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    for(int i=0;i<n;i++){
        fill(dp,dp+n,1);
        for(int j=0;j<n;j++){
            for(int k=0;k<j;k++){
                if(a[j]>a[k]) dp[j]=max(dp[j],dp[k]+1);
            }
        }
        ans=max(ans,dp[n-1]);
        rotate(a,a+1,a+n);
    }
    printf("%d",n-ans);
	return 0;
}

你可能感兴趣的:(最长上升子序列,牛客,思维)