HDU 5256 序列变换

来源:互联网 发布:墨客网络 编辑:程序博客网 时间:2024/06/06 01:41

Description

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

Input
第一行输入一个T (1 \leq T \leq 10),表示有多少组数据

每一组数据:

第一行输入一个N (1 \leq N \leq 10^5),表示数列的长度

第二行输入N个数A_1, A_2, …, A_n。

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

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

Case #i:

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

Sample Input
2
2
1 10
3
2 5 4

Sample Output
Case #1:
0
Case #2:
1
题解: 修改数量最少的元素使得这个数列严格递增,等价于让尽量多的元素不变, 然后修改其余的元素。也就是从序列里面选尽量多的数,使得其它数修改后能形成一个 单调递增序列。
a[j]-a[i]>=j-i,即是两个元素不改变需要满足两数之差大于或等于下标之差。那么对a[i]-i求最长不下降子序列,此最长非降序列里的数的个数就是不变的数的最大个数,用n减去就是答案。

由于数据量较大, 这里用了upper_bound函数,可以缩短时间,用起来也很方便,在这里用来查找dp[]中第一个比a[i]大的数的位置

下面是AC代码:

#include<stdio.h>#include<algorithm>using namespace std;#define INF 0x3f3f3f3fint a[100010],dp[100010];int i;int LIS(int n){    for(i=1;i<=n;i++)    dp[i]=INF;    int k,ans=0;    for(i=1;i<=n;i++)    {        k=upper_bound(dp+1,dp+1+n,a[i])-dp;        dp[k]=min(dp[k],a[i]);        ans=max(ans,k);    }        return ans;}int main(){    int t,j=1,n;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(i=1;i<=n;i++)        {            scanf("%d",&a[i]);            a[i]-=i;        }           printf("Case #%d:\n",j++);          printf("%d\n",n-LIS(n));            }    return 0;}
0 0