10.5比赛 T2
小 Z 爱排序( ( sorting) )
小 Z 对排序算法深有了解,但是这天他遇到了一个问题。
小 Z 需要对一个 1 到 n 的排列进行升序排序, 也就是说排序之后这个排列将
会变成 1,2,3,…,n。 但是小 Z 可以做的操作只有一种, 就是选择这个排列中的一个
元素,把它拿出来,然后接到整个排列的最前面或者最后面。比如,如果对排列
321 中的 2 进行操作,那么可以得到的排列有 231 和 312。小 Z 想知道,在最优
情况下他至少要进行几次操作才可以让这个排列升序排序?
[ [ 输入格式] ]
从 sorting.in 中读取数据。
第一行 1 个数 n,表示排列的元素数量。
接下来一行 n 个数,描述要排序的排列。
[ [ 输出格式] ]
输出一个数,表示最小操作数。
[ [ 样例输入] ]
3
3 2 1
[ [ 样例输出] ]
2
[ [ 数据范围与约定] ]
本题采用子任务制, 你只有通过同一子任务内的所有测试点才能得到这个测试点
对应的分数。
Subtask1: 包含 30Points 满足 n<=8
Subtask3: 包含 70Points 满足 n<=100000
思路:
因为只能调到第一位和最后一位,且每个数字只出现一次,也就是每个数字只移动一次。
所以如果要使步数最少,要保证原数列中连续上升数列的长度最大。
此题只需要搜索连续上升数列的长度最大值,再用总数减最大值。就可以A了
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 using namespace std; 6 int n,a[100011],x[100011]; 7 int main() 8 { 9 //freopen("sorting.in","r",stdin); 10 //freopen("sorting.out","w",stdout); 11 int i,j,h=1,daan=0; 12 cin>>n; 13 for(i=1;i<=n;i++) 14 { 15 cin>>a[i]; 16 x[a[i]]=i;//记录每个数出现位置 17 } 18 for(i=1;i<=n;i++) 19 { 20 if(x[i+1]>x[i]) 21 { 22 h++;//数列长度 23 } 24 else 25 { 26 daan=max(daan,h); 27 h=1; 28 } 29 } 30 cout<<n-daan;//总数减数列长度 31 return 0; 32 }