题面:
题意:
给定一个全排列p,可以有两种操作:
(1)将倒数第二个数放到第一个。
(2)将第一个数放到最后一个。
对于操作(1),我们将连续的几次操作都视为一次操作。
问最少进行多少次操作(1)可以将 p 变为 1...n。
题解:
我们发现若干次连续的操作(2)会让序列进行循环,即只要变为相对顺序为 1...n然后进行操作(2)循环即可到达 1...n
我们发现若干次连续的操作(2)+ 若干次连续的操作(1)的作用其实就是将序列的任意一个数插入到任意一个位置。
问题转化为,我们将序列 p 看作一个环,然后从任意位置断开,求最长上升子序列的最大值。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#include<list>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
//#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=998244353;
const double eps=1e-1;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=1010;
const int maxp=1100;
const int maxm=4000100;
const int up=100000;
int a[maxn],b[maxn];
int main(void)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),a[i+n]=a[i];
int maxx=0;
for(int i=1;i<=n;i++)
{
int cnt=0;
b[0]=0;
for(int j=i;j<=i+n-1;j++)
{
if(a[j]>b[cnt]) b[++cnt]=a[j];
else
{
int now=lower_bound(b+1,b+cnt+1,a[j])-b;
b[now]=a[j];
}
maxx=max(maxx,cnt);
}
}
printf("%d\n",n-maxx);
return 0;
}