First Last Sorting(dp+严格递增子序列)

题面

Arup has just created a data structure that makes the two following list transformations in constant O(1) time:

a. Take any element in the list and move it to the front.

b. Take any element in the list and move it to the back.

You’ve realized that sorting speed can be improved using these transformations. For example, consider the input list:

8, 3, 6, 7, 4, 1, 5, 2

We can do the following sequence of transformations to sort this list:

8, 3, 7, 4, 1, 5, 2, 6 (move 6 to end)

8, 3, 4, 1, 5, 2, 6, 7 (move 7 to end)

2, 8, 3, 4, 1, 5, 6, 7 (move 2 to front)

1, 2, 8, 3, 4, 5, 6, 7 (move 1 to front)

1, 2, 3, 4, 5, 6, 7, 8 (move 8 to end).

You are now curious. Given an input array of distinct values, what is the fewest number of these first/last operations necessary to sort the array?

The Problem:

Given an initial permutation of the integers 1, 2, …, n, determine the fewest number of first/last operations necessary to get the list of values sorted in increasing order.

The Input:

The first line of input will contain a single positive integer, n (n ≤ 1e5), representing the number of values to be sorted. The next n lines contain one integer each. All of these integers will be distinct values in between 1 and n (inclusive), representing the original order of the data to sort for the input case.

The Output:

On a line by itself, output the fewest number of first/last operations necessary to sort the input list.

题目大意

打乱一个1,2,3…n的序列,仅通过两种操作变成有序:
1.把元素放置队首
2.把元素放置对尾
最少需要多少步操作?

解题思路

很容易想到打乱序列中本就是严格递增的子序列是不需要动的
比如8, 3, 6, 7, 4, 1, 5, 2 中3,4,5就是严格递增的最长子序列,其他的元素都需要通过操作来实现归位
本题就变成了求最长严格递增子序列长度的问题

代码1

使用两个数组,一个记录打乱的数据,一个记录数据的 “地址”(在串中的位置)
然后使用模拟找下一个元素位置,求得最长严格递增子序列长度

#include"bits/stdc++.h"
using namespace std;
int
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&num[i]);
		kk[num[i]]=i;
	}
	int maxn=0;
	for(int i=1;i<=n;i++){
		int temp=num[i]+1,sum=1,tt=i;
		if(n-i+1<maxn)break;//如果剩下的元素已经小于已求得的严格递增子序列的长度就退出
		if(temp<=n){//最大边界
			while(kk[temp]>tt){//如果下一个元素的位置在当前地址之后就循环
				tt=kk[temp];
				temp++;//继续找下一个
				sum++;//记录当前严格递增子序列的长度
			}
		}
		maxn=max(maxn,sum);
	}
	cout<<n-maxn<<endl;
} 

代码2

dp [ x ]是当前以 x 结尾的严格递增子序列长度
状态更新dp[ x ]=dp[ x - 1 ] + 1

#include"bits/stdc++.h"
using namespace std;
int dp[100005],a[100005];
int main(){
	int n,m;
	int ans=0;
	cin>>n;
	memset(dp,0,sizeof(dp));
	for(int i=0;i<n;i++){
		scanf("%d",&m);
		dp[m]=dp[m-1]+1;
		ans=max(dp[m],ans);
	}
	cout<<n-ans<<endl;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值