BNU 49048 神奇的身高【思维+LIS】

351 篇文章 2 订阅

神奇的身高

Time Limit: 2000ms
Memory Limit: 65536KB
64-bit integer IO format:  %lld      Java class name:  Main
Type: 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •                   
  • 有一群小伙伴站成一行,每个人的身高都是非负整数,但是他们站在一起并不和谐。需要将他们的身高变成严格单调递增的正整数序列才是和谐的。现在你有一种神奇的魔法,可以任意改变一个人的身高。现在问题来了,你最少需要改变多少人的身高才能使整个队伍和谐。(改变后的身高必须为整数

    Input

    有多组测试数据,保证大数据不超过15组。

    每组测试数据:

    第1行:一个数n表示人数(1≤n≤100000)

    第2~n+1行:每行1个数,对应数组的元素(0≤A[i]≤10^9)

    以EOF结束

    Output

    输出最少需要修改几人的身高才能使整个队伍和谐。

    Sample Input

    2
    1
    2
    2
    2
    1
    

    Sample Output

    0
    1
    

    Source

    Author

    zpk
    思路:


    本题和百度之星hdu 5256比较相似。

    我们希望得到一个序列为:1 2 3 4 5 6 7 8 9 10...................

    那么我们不妨相对得到即可。

    所以我们跑(a【i】-i)的LIS(这里跑最长非递减)就行。

    但是这里要求数据最终不能有<=0的数据存在,那么所以如果a【i】-i<0,就一定不属于LIS的部分,因为其如果属于了,又参与到了最长上升子序列中了,那么结果就会出现负数的情况。

    所以我们只要对于(a【i】-i)>0的部分跑LIS即可。


    Ac代码:

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    int a[1050000];
    int f[1050000];
    int Slove(int n)
    {
        int c=0;
        for(int i=1; i<=n; i++)
        {
            int t=a[i];
            if(t<0)continue;
            if(i==1) f[++c]=t;
            else
            {
                if(t>=f[c]) f[++c]=t;
                else
                {
                    int pos=upper_bound(f+1,f+c,t)-f;//二分找到数组中比t大的第一个元素的的地址。
                    f[pos]=t;
                }
            }
        }
        return c;
    }
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            for(int i=1;i<=n;i++)
            {
                int x;
                scanf("%d",&x);
                a[i]=x-i;
            }
            printf("%d\n",n-Slove(n));
        }
    }
    









    • 0
      点赞
    • 1
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值