BNUOJ-49098-神奇的身高

神奇的身高
Time Limit: 2000msMemory Limit: 65536KB 64-bit integer IO format: %lld Java class name: Main
Prev Submit Status Statistics Discuss Next
Type:
None

Tag it!
有一群小伙伴站成一行,每个人的身高都是非负整数,但是他们站在一起并不和谐。需要将他们的身高变成严格单调递增的正整数序列才是和谐的。现在你有一种神奇的魔法,可以任意改变一个人的身高。现在问题来了,你最少需要改变多少人的身高才能使整个队伍和谐。(改变后的身高必须为整数)

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

思路:接收的数据减去自己的下标再存进数组。不能直接对原序列求最长上升子序列长度,因为如果出现类似4,4,5的情况,由于4,4相同,所以需要改变2个数字,而拿总长度减去最长上升子序列长度的值却为1,接下来用几个变量处理这种特殊情况。
num_1记录原数据减去自己下标后小于1的数据的数量,并舍弃这个原数据
num_2记录未舍弃的被处理过的数据数量
num_3记录处理过的数据中最长上升子序列的长度
最终结果就是num_1+num_2-num_3

BUG:题中给出数据范围是0到10的9次方
而对于这组数据
4
0 0 1 2
程序运行结果是4,实际答案应该是3.
然而由于后台数据比较水,还是给了AC

DEBUG:我不会

代码

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<queue>
#include<stack>
using namespace std;
const int maxn=100005;
int num[maxn];//接收数据
int flag[maxn];//辅助数组
int dp[maxn];//动规
int main()
{
    int n;//人数
    while(~scanf("%d",&n))
    {
        int num_1=0;
        int num_2=0;
        int num_3=0;
        int num_4=0;
        for(int i=0; i<n; i++)
        {
            scanf("%d",&num[i]);//接收数据
            num[i]=num[i]-i;
            num[i]<1?num_1++:flag[num_2++]=num[i];//记录num_1,num_2
        }
        for(int i=0; i<num_2; i++)//求LIS长度num_3
        {
            num_4=upper_bound(dp,dp+num_3,flag[i])-dp;
            num_4==num_3?dp[num_3++]=flag[i]:dp[num_4]=flag[i];
        }
        num_1=num_1+num_2-num_3;
        printf("%d\n",num_1);
    }
    return 0;
}

下面这段代码来自http://blog.csdn.net/libin56842/article/details/45645231
更简洁也更难懂

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
//来自网络
const int INF=0x3f3f3f3f;
int n,b[100005],ans;
int main()
{
    int i,j,k,x;
    while(~scanf("%d",&n))
    {
        ans=0;
        for(int i=0; i<=n; i++)
            b[i]=INF;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&x);
            if(x-i+1<=0)
                continue;
            k=upper_bound(b+1,b+1+n,x-i)-b;
            b[k]=x-i;
            ans=max(ans,k);
        }
        printf("%d\n",n-ans);
    }
    return 0;
}

对于upper_bound,这是STL标准模版库的函数,用于返回在一定范围内查找指定元素的下标值,这一段完全可以用模板LIS代替

一道裸的LIS http://blog.csdn.net/qq_32680617/article/details/50807824

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值