• 51Nod 1294 修改数组 —— LIS


    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1294

    题目来源: HackerRank
    基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题
     收藏
     关注
    给出一个整数数组A,你可以将任何一个数修改为任意一个正整数,最终使得整个数组是严格递增的且均为正整数。问最少需要修改几个数?
    Input
    第1行:一个数N表示序列的长度(1 <= N <= 100000)。
    第2 - N + 1行:每行1个数,对应数组元素。(0 <= A[i] <= 10^9)
    Output
    输出最少需要修改几个数使得整个数组是严格递增的。
    Input示例
    5
    1
    2
    2
    3
    4
    Output示例
    3

    题意:

    给出一个数列,问至少修改多少个数,使得序列:全为正整数且严格单调递增。

    题解:

    1.首先,不需要修改的数构成了这个数列的“骨架”,这个“骨架”且满足:b[i].val-b[j].val>=b[i].index-b[j].index, i>j,这条不等式限制了在骨架点i和j之间,必须有足够范围的数。

    2.可知第一个数最小为1,第二个数最小为2,……第i个数最小为i。

    3.根据第2点,可以得出一个结论:当a[i]<i时,a[i]必须修改;当a[i]>=i时,a[i]可能不需要修改。

    4.所以将可能不需要修改的数(包括数值和其所在的位置)提取出来,放到结构体数组b[]当中,然后求b[]数组的LIS(需满足:b[i].val-b[j].val>=b[i].index-b[j].index, i>j),即为整个序列的“骨架”,在“骨架上”的数都不需要修改,所以:ans = n - LIS_LEN 。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cmath>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 2e9;
    15 const LL LNF = 9e18;
    16 const int MOD = 1e9+7;
    17 const int MAXN = 1e5+10;
    18 
    19 struct node
    20 {
    21     int val, pos;
    22 };
    23 node a[MAXN], dp[MAXN];
    24 
    25 bool ok(node x, node y)
    26 {
    27     return (x.val-y.val)>=(x.pos-y.pos);
    28 }
    29 
    30 int Search(node dp[], int n, node x)
    31 {
    32     int l = 1, r = n;
    33     while(l<=r)
    34     {
    35         int mid = (l+r)>>1;
    36         if(ok(x,dp[mid]))
    37             l = mid + 1;
    38         else
    39             r = mid - 1;
    40     }
    41     return r;
    42 }
    43 
    44 int main()
    45 {
    46     int n, m;
    47     while(scanf("%d", &n)!=EOF)
    48     {
    49         for(int i = 1; i<=n; i++)
    50             scanf("%d",&a[i].val);
    51         m = 0;
    52         for(int i = 1; i<=n; i++)
    53             if(a[i].val>=i)
    54                 a[++m].val = a[i].val, a[m].pos = i;
    55 
    56         int len = 0;
    57         for(int i = 1; i<=m; i++)
    58         {
    59             if(i==1||ok(a[i],dp[len]))
    60                 dp[++len] = a[i];
    61             else
    62             {
    63                 int pos = Search(dp,len,a[i]);
    64                 dp[pos+1] = a[i];
    65             }
    66         }
    67         printf("%d
    ", n-len);
    68     }
    69 }
    View Code
  • 相关阅读:
    46、Spark SQL工作原理剖析以及性能优化
    45、sparkSQL UDF&UDAF
    44、开窗函数及案例
    43、内置函数及每日uv、销售额统计案例
    42、JDBC数据源案例
    41、Hive数据源复杂综合案例
    40、JSON数据源综合案例实战
    39、Parquet数据源之自动分区推断&合并元数据
    Java 的String类
    Java学习之旅基础知识篇:面向对象之封装、继承及多态
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8708500.html
Copyright © 2020-2023  润新知