序列变换(O(n))

题面描述:

题目描述
给定一个长度为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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值