题目描述
已知一个奇怪的队列,这个队列中有n个数,初始状态时,顺序是1,2,3,4,…n,是1-n按顺序排列。这个队列只支持一种操作,就是把队列中的第i号元素提前到队首(1<i<=n),如有4个元素,初始为1,2,3,4,可以将3提前到队首,得到3,1,2,4 。 现在给出一个经过若干次操作之后的序列,请你找出这个序列至少是由原序列操作了多少次得到的。
输入描述
第一行是一个整数n(1<=n<=10^5),表示序列中数字的数量。 接下来一行有n个数,是1-n的一个全排列。数字之间用空格隔开。
输出描述
输出仅包含一个数字,表示至少操作了几次。
示例
输入:
5
5 2 1 3 4
输出:
2
解题思路
队列中的元素只能提到最前面,问至少操作多少次能够将1,2,3,…n的排列变成如题的排列,反过来就是至少需要多少次才能将队列恢复成1,2,…n的排列,注意只能将队首的元素向后放置到任意位置。
操作最少就是操作最少的元素,对于一个元素,如果它的后面有比它小的元素,那么这个元素必须要移动,否则就无法实现顺序。
那么从队首元素开始寻找顺序序列,如果后一个元素大于前一个元素,继续向后,如果小于前一个元素,那么将这段顺序序列全部移动,并且以这个小的元素作为第一个元素开始一段新的顺序序列的查找,直到遍历完所有元素。
代码实现
#include <iostream>
using namespace std;
int main(){
int n;
cin>>n;
int cnt=0;
int sum=0;
int val;
int minx=-1;
for(int i=0;i<n;i++){
cin>>val;
if(val>minx)
cnt++;
else if(val<minx){
sum+=cnt;
cnt=1;
}
minx=val;
}
cout<<sum<<endl;
}
关于通过移动元素完成队列顺序性有一道类似的题目,参见另一篇文章排序次数。