题面描述:
题目描述
给定一个长度为N的数列Ai。
你可以对数列进行若干次操作,每次操作可以从数列中任选一个数,把它移动到数列的开头或者结尾。
求最少经过多少次操作,可以把数列变成单调不减的。“单调不减”意味着数列中的任意一个数都不大于排在它后边的数。
输入格式
第一行是一个正整数N。
第二行是N个正整数Ai。
输出格式
输出一个整数,表示最少需要的操作次数。
样例输入
5
6 3 7 8 6
样例输出
2
数据范围与约定
对于30%的数据,满足1≤n≤10。
对于60% 的数据,满足1≤n≤1000。
对于100% 的数据,满足1≤n≤1000000,1≤Ai≤1000000。
这道题相当玄妙(鉴于数据的水)
当我听到有人这道题直接交了最小上升子序列就拿了50分
这让我悲伤我想了好久的如何处理一个数出现多次。。
本来我也觉得最小上升子序列没有问题,但是发现样例多次没有过之后就。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
但是,中心思想永远是,维护一个序列,除了这个序列的数以外的所有的数都要移动,我先是觉得是子序列,子串,然后都轻易的找出了反例。
最长上升子序列:只要一个数出现了两次肯定错的。
最长上升子串:1 3 4 2 5 最小上升子串是3 4 或者2 5,但只要移动两次,。
然后我聪明的同桌指出了我的最大来连续子串 的错误,这道题,应该是找一个最长连续子序列。
连续即离散化后的序号是连续的。
(离散化emmm,我举个例子,1 8 9 100,可以离散化为 1 2 3 4)
比如说上一个 1 3 4 2 5,最小连续子序列是多少呢?
3 4 5
所以答案是2
但是这道题很恶心的地方在于,某个数可以出现多次,所以离散化有点特殊。
for (int i=1; i<=1000000; i++)
{
if (c[i]>0)
{
e[i]=x;
d[i]=++t;
x=t;
t+=c[i]-1;
}
}
数组解释:
c表示桶排序每一个数字出现的次数,以便离散化以及后面统计重复数字的出现
d表示每一个数在离散化数组中的序号
e表示a[i]前一个数值的离散化序号。 譬如 8 8 10,e[10]=8;
譬如说当前这个数是a[i], e[i],d[a[i]−1] e [ i ] , d [ a [ i ] − 1 ] 的区别是什么呢?
比如说
7 8 8 10
e[10] e [ 10 ] —— > > 8