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

原题
题目描述
Inaka创作音乐。今天的排列包括n个音符和弦,用排列p_1,p_2,…p_n表示从低到高的音符。
她的朋友Miyako并通过以下两个操作更改和弦:
Drop-2:取出第二高音符并将其移至最低位置,即将排列更改为pn-1,p1,p2,…,pn-3,pn-2,pn。
反转:取出最低音符并将其移至最高位置,即,将排列更改为p2,p3,…,pn-1,pn,p1。
任意数量的连续Drop-2操作都被视为一个multi-drop。 Miyako希望以最少的multi-drop数目将排列更改为有序排列1,2,…,n。请帮助她找到所需的multi-drop数目。

输入描述:
第一行包含整数n(2≤n≤500),即音符数。
第二行包含n个以空格分隔的整数p1,p2,…,pn,即音符的原始排列。输入保证从1到n(包括1和n)的每个整数在排列中恰好出现一次。
输出描述:输出一个整数,即将排列更改为有序整数所需的多点数目。
样例1
输入

6
2 4 5 1 3 6

输出

2

说明

An optimal solution with two multi-drops is:
- Invert, 5 times, changing the permutation to 6,2,4,5,1,3;
- Drop-2, 3 times, changing the permutation to 4,5,1,6,2,3;
- Invert, 4 times, changing the permutation to 2,3,4,5,1,6;
- Drop-2, 1 time, changing the permutation to 1,2,3,4,5,6.

样例2
输入

8
8 4 7 3 6 2 5 1

输出

5

思路
刚开始并不知道这道题要我们干什么,但是经过旁边同学的指点,我懂了。
只需要把它看成一个圆盘,这并不改变元素本身的值,只会改变相对位置。所以可以想到这是一个最长不下降子序列。
代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int ans,n,a[maxn*2],dp[maxn];
int v(int left,int right)
{
	int sum=0;
    for(int i=left;i<=right;i++) dp[i]=1;
    for(int i=left+1;i<=right;i++)
    {
        for(int j=left;j<i;j++)if(a[j]<a[i])dp[i]=max(dp[i],dp[j]+1);
        sum=max(sum,dp[i]);
    }
    return sum;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i+n]=a[i];
    for(int i=1;i<=n;i++)ans=max(ans,v(i,i+n-1));
	printf("%d",n-ans); 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/bbbll123/article/details/107584140
今日推荐