题目描述
Inaka composes music. Today's arrangement includes a chord of notes that are pairwise distinct, represented by a permutation of integers from to (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. : Take out the second highest note and move it to the lowest position, i.e. change the permutation to . Invert: Take out the lowest note and move it to the highest position, i.e. change the permutation to .
Any number of consecutive operations is considered a multi-drop. Miyako would like to change the permutation to an ordered permutation, , in the fewest number of possible. Please help her find the number of needed.
输入描述
The first line contains an integer — the number of notes.
The second line contains n space-separated integers — the original permutation of notes.
The input guarantees each integer from to (inclusive) appears in the permutation exactly once.
输出描述
Output one integer — the number of required to change the permutation to an ordered one.
示例1
输入
6 2 4 5 1 3 6
输出
2
说明
An optimal solution with two multi-drops is:
Invert, times, changing the permutation to ;
, times, changing the permutation to ;
, times, changing the permutation to ;
, time, changing the permutation to .
示例2
输入
8 8 4 7 3 6 2 5 1
输出
5
分析
对于操作 ,可以将 看作一个环,环的长度为 ,即进行 次操作 ,排列还原;对于操作 ,可以将 看作一个环,环的长度为 ,即进行 次操作 ,排列还原。形成的两个环如图所示, 代表当前排列 的第一个数, 代表位于大环(长度为 的环)上,而在小环(长度为 的环)外的数。
小环和大环可以独立顺时针转动,两个指针 和 的位置是固定不动的;当转动小环,视为进行了一次 ,当转动大环,视为进行多次 。可以发现,当转动小环,可以将位于小环外的数字,插入任意两个数字之间。在图中,当前 位于 和 之间,转动一次小环, 就在 和 之间了;显然,进行一次 ,可以将 放入任何你想要的位置。更一般的,若要该边数字 在大环中的相对其他数字位置,应该首先用多次 将 放入 标记的位置,然后进行一次 。我们要对大环上的数字进行排序,那么只需要通过若干次操作,利用小环调整一些数字的相对位置,令大环上形成 这样的环,再进行几次 即可将原序列 完成排序。
那么问题就变得简单:每次调整一个数的位置就要进行一次 ,因此要调整尽可能少的数字。不妨找出大环上的一个 (最长上升子序列),其长度为 ;对于在 上的 个数字不作调整,只需要调整 个数字的相对位置;显然,这样的方案使得需要调整的数字个数最小。对于不在 上的 个数字,用 次 和若干次 ,即可将这 个数字一一放入正确的位置,完成排序。
计算环上的 长度时,可以枚举环的起点,对 个起点各求一次 ,取长度最大的即可。时间复杂度为 。
代码
/****************************************************************** Copyright: 11D_Beyonder All Rights Reserved Author: 11D_Beyonder Problem ID: 2020牛客暑期多校训练营(第五场) Problem D Date: 8/20/2020 Description: Circle, LIS *******************************************************************/ #include<algorithm> #include<iostream> #include<cstdio> using namespace std; const int N=504; int n; int p[N]; int a[N]; int dp[N]; int main(){ cin>>n; int i,j; for(i=1;i<=n;i++){ scanf("%d",p+i); } int ans=0x3f3f3f3f; //枚举环的起点 for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ //环确定了起点为i //于是可以环拉成链 a[j]=p[i+j-1-n*(i+j-1>n)]; } //求LIS int len=1; dp[1]=a[1]; for(j=2;j<=n;j++){ if(a[j]>dp[len]){ dp[++len]=a[j]; }else{ *lower_bound(dp+1,dp+1+len,a[j])=a[j]; } } ans=min(n-len,ans);//最小调整次数 } cout<<ans<<endl; return 0; }