【SSL】1652CIM
Time Limit:1000MS
Memory Limit:65536K
Description
给出一个1到n的排列,每次可以移动一个数到一个任意位置。问要达到状态1,2,3……n至少移动多少次?
Input
n (1<=n<=100000)
n个数
Output
移动次数!
Sample Input
5
2 1 4 5 3
Sample Output
2
思路
答案就是N减去这个排列的最长上升子序列的长度。因为除了最长上升子序列里的数,其他数都要移动到正确位置。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iomanip>
using namespace std;
int n,a[100010],f[100010],ans;
void input()
{
int i;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
return;
}
int erfind(int s)
{
int l=1,r=ans,mid;
do
{
mid=(l+r)/2;
if (f[mid]<s)
{
l=mid+1;
}
else
{
r=mid-1;
}
}
while(l<=r);
return l;
}
void DP()
{
int i;
f[1]=a[1];
ans=1;
for(i=2;i<=n;i++)
{
if (a[i]>=f[ans])
{
ans++;
f[ans]=a[i];
}
else
{
f[erfind(a[i])]=a[i];
}
}
return;
}
int main()
{
input();
DP();
printf("%d",n-ans);
return 0;
}