云计算百科
云计算领域专业知识百科平台

小苯的数组构造【牛客tracker & 每日一题】

小苯的数组构造

时间限制:1 秒 空间限制:256M

网页链接

牛客tracker

牛客tracker & 每日一题,完成每日打卡,即可获得牛币。获得相应数量的牛币,能在【牛币兑换中心】,换取相应奖品!助力每日有题做,丰盈牛币日益多! 在这里插入图片描述


题目描述

大白熊给了小苯一个长度为

n

n

n 的数组

a

a

a,他希望小苯将数组

a

a

a 变成有序(非递减)的。具体的,小苯需要进行如下操作:

  • 任选一个数组

    b

    b

    b,长度也为

    n

    n

    n,且元素满足:

    −

    10

    10

    ≤

    b

    i

    ≤

    10

    10

    -10^{10} \\le b_i \\le 10^{10}

    −1010≤bi​≤1010。

  • 对于所有

    1

    ≤

    i

    ≤

    n

    1 \\le i \\le n

    1≤i≤n,都执行

    a

    i

    =

    a

    i

    +

    b

    i

    a_i = a_i + b_i

    ai​=ai​+bi​。

  • 大白熊希望在执行完操作后

    a

    a

    a 数组满足有序,同时要最小化数组

    b

    b

    b 的极差,即使得:

    max

    ⁡

    (

    b

    1

    ,

    b

    2

    ,

    …

    ,

    b

    n

    )

    −

    min

    ⁡

    (

    b

    1

    ,

    b

    2

    ,

    …

    ,

    b

    n

    )

    \\max(b_1, b_2, \\dots, b_n) – \\min(b_1, b_2, \\dots, b_n)

    max(b1​,b2​,…,bn​)−min(b1​,b2​,…,bn​)

    最小。

    请你帮小苯找出一个合法的

    b

    b

    b 数组吧。

    注:如有多解输出任意即可。


    输入描述

    输入包含两行。

    • 第一行一个正整数

      n

       

      (

      1

      ≤

      n

      ≤

      2

      ×

      10

      5

      )

      n\\ (1 \\le n \\le 2 \\times 10^5)

      n (1≤n≤2×105),表示

      a

      a

      a 的长度。

    • 第二行

      n

      n

      n 个整数

      a

      i

       

      (

      −

      10

      9

      ≤

      a

      i

      ≤

      10

      9

      )

      a_i\\ (-10^9 \\le a_i \\le 10^9)

      ai​ (−109≤ai​≤109),表示数组

      a

      a

      a 的元素。


    输出描述

    输出包含一行

    n

    n

    n 个整数,表示构造出的

    b

    b

    b 数组(有多解输出任意即可)。

    如果找不到合法的

    b

    b

    b 数组,请输出一个整数

    −

    1

    -1

    −1。


    示例 1

    输入:

    2
    1 2

    输出:

    114514 114514

    说明: 可以构造

    b

    =

    [

    114514

    ,

    114514

    ]

    b = [114514, 114514]

    b=[114514,114514],这样

    b

    b

    b 的极差为

    0

    0

    0,可以证明不存在比

    0

    0

    0 更小的极差。


    备注

    数组的极差 = 数组中的最大值减去最小值。


    数据范围与提示

    • 1

      ≤

      n

      ≤

      2

      ×

      10

      5

      1 \\le n \\le 2 \\times 10^5

      1≤n≤2×105

    • −

      10

      9

      ≤

      a

      i

      ≤

      10

      9

      -10^9 \\le a_i \\le 10^9

      −109≤ai​≤109

    • −

      10

      10

      ≤

      b

      i

      ≤

      10

      10

      -10^{10} \\le b_i \\le 10^{10}

      −1010≤bi​≤1010

    • 核心思路:
    • 记最终序列

      f

      i

      =

      a

      i

      +

      b

      i

      f_i = a_i + b_i

      fi​=ai​+bi​,要求

      f

      f

      f 非递减。

      b

      b

      b 的极差等价于

      max

      ⁡

      i

      (

      f

      i

      −

      a

      i

      )

      −

      min

      ⁡

      i

      (

      f

      i

      −

      a

      i

      )

      \\max_i(f_i – a_i) – \\min_i(f_i – a_i)

      maxi​(fi​−ai​)−mini​(fi​−ai​),要让它最小。

    • 两种自然的构造可分别给出上界:
      • 取

        b

        i

        =

        p

        m

        x

        i

        −

        a

        i

        b_i = \\mathrm{pmx}_i – a_i

        bi​=pmxi​−ai​(

        p

        m

        x

        i

        \\mathrm{pmx}_i

        pmxi​ 为前缀最大值),此时

        f

        i

        =

        p

        m

        x

        i

        f_i = \\mathrm{pmx}_i

        fi​=pmxi​ 非递减,

        b

        b

        b 的极差为

        max

        ⁡

        i

        (

        p

        m

        x

        i

        −

        a

        i

        )

        \\max_i(\\mathrm{pmx}_i – a_i)

        maxi​(pmxi​−ai​);

      • 取

        b

        i

        =

        s

        m

        n

        i

        −

        a

        i

        b_i = \\mathrm{smn}_i – a_i

        bi​=smni​−ai​(

        s

        m

        n

        i

        \\mathrm{smn}_i

        smni​ 为后缀最小值),此时

        f

        i

        =

        s

        m

        n

        i

        f_i = \\mathrm{smn}_i

        fi​=smni​ 非递减,

        b

        b

        b 的极差为

        max

        ⁡

        i

        (

        a

        i

        −

        s

        m

        n

        i

        )

        \\max_i(a_i – \\mathrm{smn}_i)

        maxi​(ai​−smni​)。

    • 最优极差为

      D

      =

      min

      ⁡

      {

      max

      ⁡

      i

      (

      p

      m

      x

      i

      −

      a

      i

      )

      ,

       

      max

      ⁡

      i

      (

      a

      i

      −

      s

      m

      n

      i

      )

      }

      D = \\min\\left\\{ \\max_i(\\mathrm{pmx}_i – a_i),\\ \\max_i(a_i – \\mathrm{smn}_i) \\right\\}

      D=min{imax​(pmxi​−ai​), imax​(ai​−smni​)} 选择上述两种构造中更优的一种输出即可(也可以在此基础上统一平移,使得所有

      b

      i

      b_i

      bi​ 都落在

      [

      −

      10

      10

      ,

      10

      10

      ]

      [-10^{10}, 10^{10}]

      [−1010,1010] 内)。

    • 由于

      ∣

      a

      i

      ∣

      ≤

      10

      9

      |a_i| \\le 10^9

      ∣ai​∣≤109,构造出的

      b

      i

      b_i

      bi​ 绝对值不会超过

      2

      ×

      10

      9

      2 \\times 10^9

      2×109,必然满足约束,因此答案永远不会是

      −

      1

      -1

      −1(该分支仅为格式完备保留)。

    • 时间复杂度

      O

      (

      n

      )

      O(n)

      O(n)。

    解题思路

    本题是构造 + 贪心的经典问题。给定一个长度为

    n

    n

    n 的数组

    a

    a

    a,需要构造一个数组

    b

    b

    b,使得

    a

    i

    +

    b

    i

    a_i + b_i

    ai​+bi​ 构成非递减序列,并且数组

    b

    b

    b 的极差(最大值减最小值)尽可能小。要求输出任意一个满足条件的

    b

    b

    b 数组。

    1. 问题等价转化
    • 设最终序列为

      f

      i

      =

      a

      i

      +

      b

      i

      f_i = a_i + b_i

      fi​=ai​+bi​。要求

      f

      f

      f 非递减,即

      f

      1

      ≤

      f

      2

      ≤

      ⋯

      ≤

      f

      n

      f_1 \\le f_2 \\le \\dots \\le f_n

      f1​≤f2​≤⋯≤fn​。

    • 数组

      b

      b

      b 的极差为

      max

      ⁡

      (

      b

      i

      )

      −

      min

      ⁡

      (

      b

      i

      )

      =

      max

      ⁡

      (

      f

      i

      −

      a

      i

      )

      −

      min

      ⁡

      (

      f

      i

      −

      a

      i

      )

      \\max(b_i) – \\min(b_i) = \\max(f_i – a_i) – \\min(f_i – a_i)

      max(bi​)−min(bi​)=max(fi​−ai​)−min(fi​−ai​)。

    • 由于我们可以对

      b

      b

      b 整体平移(同时加上或减去一个常数),极差不变,因此不妨令

      min

      ⁡

      (

      b

      i

      )

      =

      0

      \\min(b_i) = 0

      min(bi​)=0,即存在某个

      i

      i

      i 使得

      b

      i

      =

      0

      b_i = 0

      bi​=0,从而

      f

      i

      =

      a

      i

      f_i = a_i

      fi​=ai​。

    • 为了使

      f

      f

      f 非递减且

      b

      i

      ≥

      0

      b_i \\ge 0

      bi​≥0,一个自然的构造是令

      f

      i

      f_i

      fi​ 等于

      a

      a

      a 的前缀最大值:

      f

      i

      =

      pmx

      i

      =

      max

      ⁡

      j

      ≤

      i

      a

      j

      f_i = \\text{pmx}_i = \\max_{j \\le i} a_j

      fi​=pmxi​=j≤imax​aj​ 这样

      f

      i

      f_i

      fi​ 显然非递减,且

      f

      i

      ≥

      a

      i

      f_i \\ge a_i

      fi​≥ai​,所以

      b

      i

      =

      pmx

      i

      −

      a

      i

      ≥

      0

      b_i = \\text{pmx}_i – a_i \\ge 0

      bi​=pmxi​−ai​≥0。当

      a

      i

      a_i

      ai​ 本身是前缀最大值时,

      b

      i

      =

      0

      b_i = 0

      bi​=0,因此

      min

      ⁡

      (

      b

      i

      )

      =

      0

      \\min(b_i) = 0

      min(bi​)=0。

    • 此时

      b

      b

      b 的极差为:

      max

      ⁡

      i

      b

      i

      −

      min

      ⁡

      i

      b

      i

      =

      max

      ⁡

      i

      (

      pmx

      i

      −

      a

      i

      )

      −

      0

      =

      max

      ⁡

      i

      (

      pmx

      i

      −

      a

      i

      )

      \\max_i b_i – \\min_i b_i = \\max_i (\\text{pmx}_i – a_i) – 0 = \\max_i (\\text{pmx}_i – a_i)

      imax​bi​−imin​bi​=imax​(pmxi​−ai​)−0=imax​(pmxi​−ai​) 可以证明,这个值就是所有合法构造中极差的最小值(与另一种后缀最小值构造得到的极差相等)。因此该构造即为最优解。

    2. 算法实现
  • 读入

    n

    n

    n 和数组

    a

    a

    a。

  • 初始化 mx 为一个极小值(如 -INF),用于记录当前前缀最大值。
  • 遍历

    i

    =

    1

    ∼

    n

    i = 1 \\sim n

    i=1∼n:

    • 更新 mx = max(mx, a[i])。
    • 计算 b[i] = mx – a[i]。
  • 输出数组 b。
  • 3. 复杂度分析
    • 时间复杂度:只需一次线性遍历,

      O

      (

      n

      )

      O(n)

      O(n)。

      n

      ≤

      2

      ×

      10

      5

      n \\le 2 \\times 10^5

      n≤2×105,非常快。

    • 空间复杂度:需要存储数组

      a

      a

      a 和

      b

      b

      b,

      O

      (

      n

      )

      O(n)

      O(n)。也可以边读边算,只存

      b

      b

      b。

    总结

    通过令最终序列等于原数组的前缀最大值,构造出的

    b

    i

    =

    pmx

    i

    −

    a

    i

    b_i = \\text{pmx}_i – a_i

    bi​=pmxi​−ai​ 保证了最终序列非递减,且

    b

    i

    ≥

    0

    b_i \\ge 0

    bi​≥0,最小值必为

    0

    0

    0。此时极差等于最大的前缀差值,该值被证明是最小的。算法简单高效,直接输出即可。

    代码简要说明

    • 使用 long long 存储数组,防止溢出。
    • INF 取 0x3f3f3f3f3f3f3f3f 作为极小值初始化 mx。
    • 遍历数组,维护前缀最大值 mx,同时计算 b[i] = mx – a[i]。
    • 最后按顺序输出 b 数组,空格分隔。

    代码内容

    #include <bits/stdc++.h>
    using namespace std;

    #define endl '\\n'
    typedef long long ll;
    typedef unsigned long long ull;
    typedef vector<vector<ll>> vvt;
    typedef pair<ll,ll> pll;
    const ll N=1e3+10;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const ll M=1e6+10;
    const ll mod=1000000007;

    ll a[200005];
    ll b[200005];

    void solve()
    {
    ll n;
    cin>>n;
    for(ll i=1;i<=n;i++) cin>>a[i];
    ll mx=–INF;
    for(ll i=1;i<=n;i++)
    {
    if(a[i]>mx) mx=a[i];
    b[i]=mx–a[i];
    }
    for(ll i=1;i<=n;i++) cout<<b[i]<<" ";
    cout<<endl;
    }

    int main()
    {
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t=1;

    while(t—) solve();
    return 0;
    }

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 小苯的数组构造【牛客tracker & 每日一题】
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!