本题着重考察边界的处理,极其微妙,注意思维的严谨性

核心思路

核心观察

情况一:原数组最大相邻差

  • 此时,我们只需将所有相邻差 压缩至不超过

  • 对于每对相邻元素 ,设

    • :无需操作;
    • :需插入若干数,使得每段跳跃
  • 最少插入数为:

情况二:原数组最大相邻差

  • 此时所有相邻差都小于 ,平滑值
  • 但我们可以在数组末尾添加一个数(例如 ),使得最后一段差为
  • 这样,平滑值变为 ,满足要求。
  • 仅需 1 次操作

注意:例如,但是k为5,只需要在1,2之间插入6即可。

算法步骤

  1. 读入数组 和参数
  2. 遍历相邻元素,计算最大差 maxd 和总操作次数 ans
    • 对每个差
      • ,累加插入次数:(d + k - 1) / k - 1 或等价形式;
  3. maxd < k,输出 1
  4. 否则,输出 ans

复杂度分析

  • 时间复杂度 单次遍历整个数组,甚至边输入边遍历

  • 空间复杂度
    只需储存数组,当然你也可以

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
    int n;cin>>n;
    int k;cin>>k;
    vector v(n,0);
    int ans=0,mx=0;cin>>v[0];
    for(int i=1;i<n;i++){
        cin>>v[i];
        int tem=abs(v[i]-v[i-1]);
        mx=max(mx,tem);
        ans+=tem/k;
        if(tem%k==0&&tem!=0)ans-=1;
    }
    if(mx<k)cout<<1;
    else cout<<ans;
}

流程图

flowchart TD
    A[开始] --> B[读取数组 a 和 k]
    B --> C[初始化 maxd = 0, ans = 0]
    C --> D[遍历数组 i = 1 到 n-1]
    D --> E["计算 d = |a[i] - a[i-1]|"]
    E --> F["更新 maxd = max(maxd, d)"]
    F --> G{d > k?}
    G -- 是 --> H[累加操作次数:ans]
    G -- 否 --> I[无需操作]
    H --> J[继续下一个元素]
    I --> J
    J --> K{i == n-1?}
    K -- 否 --> D
    K -- 是 --> L{maxd < k?}
    L -- 是 --> M[输出 1(在末尾添加一个数使差值=k)]
    L -- 否 --> N[输出 ans]
    M --> O[结束]
    N --> O