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