HDU - 5256 序列变换 (LIS转化)

来源:互联网 发布:数据库配置文件怎么写 编辑:程序博客网 时间:2024/05/20 16:41
HDU - 5256
序列变换
Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u

Submit Status

Description

我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增。其中无论是修改前还是修改后,每个元素都必须是整数。 
请输出最少需要修改多少个元素。
 

Input

第一行输入一个,表示有多少组数据 

每一组数据: 

第一行输入一个,表示数列的长度 

第二行输入N个数 

每一个数列中的元素都是正整数而且不超过
 

Output

对于每组数据,先输出一行 

Case #i: 

然后输出最少需要修改多少个元素。
 

Sample Input

221 1032 5 4
 

Sample Output

Case #1:0Case #2:1
 

Source

2015年百度之星程序设计大赛 - 初赛(2)
//思路:
看到这个题第一思想就是先求出序列的LIS的最长长度top,再用n-top即为所求。这个思路没错,但是得转化一下(刚开始没有转化,测试了几组数据过了,但一交WA了),因为如果碰到这样一个例子:1  2  2  2  3,top=3,答案为n-top=2;但显然是错的,因为你要在1---2之间加两个整数,这显然是不合理的,所以就得转化一下避免这样的错误。转化:在输入序列的每个数的时候直接用这个数减去它的下标值,就可以避免上面的错误了。
因为数的个数很多,有平常的求LIS肯定超时,所以要用二分方法的LIS,并且求的这个LIS是非严格的(包括相等的)。因为在转化后,即使两个数是相等的,它们减的下标是不同的,所以他们转化回去依旧是严格递增的。比如:1  2  3  4  5,转化后为位0  0  0  0  0,但它们转化回去是严格递增的。所以有了这个转换后,再在二分方法求LIS的模板上稍微修改一下就可以了。
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>#include<map>#include<queue>#include<stack>#define INF 0x3f3f3f3f#define ull unsigned lonb long#define ll long long#define IN __int64#define N 1000010#define M 1000000007using namespace std;int a[N];int main(){int T=1,t,n,m,i,j;int top;int l,r,mid;scanf("%d",&t);while(t--){scanf("%d",&n);memset(a,0,sizeof(a));top=0;a[0]=-INF;for(i=1;i<=n;i++){scanf("%d",&m);m-=i;if(m>=a[top])a[++top]=m;else{l=1;r=top;while(l<=r){mid=(l+r)/2;if(m>=a[mid])l=mid+1;elser=mid-1;}a[l]=m;}}printf("Case #%d:\n%d\n",T++,n-top);}return 0;}

0 0
原创粉丝点击