AtCoder题解 —— AtCoder Beginner Contest 185 —— D - Stamp —— 模拟

题目相关

题目链接

AtCoder Beginner Contest 185 D 题,https://atcoder.jp/contests/abc185/tasks/abc185_d

Problem Statement

There are N squares arranged in a row from left to right. Let Square i be the i-th square from the left.
M of those squares, Square A1, A2, A3, …, AM, are blue; the others are white. (M may be 0, in which case there is no blue square.)
You will choose a positive integer k just once and make a stamp with width k. In one use of a stamp with width k, you can choose k consecutive squares from the N squares and repaint them red, as long as those k squares do not contain a blue square.
At least how many uses of the stamp are needed to have no white square, with the optimal choice of k and the usage of the stamp?

Input

Input is given from Standard Input in the following format:

N M
A1 A2 A3 … AM

Output

Print the minimum number of uses of the stamp needed to have no white square.

Samples1

Sample Input 1

5 2
1 3

Sample Output 1

3

Explaination

If we choose k=1 and repaint the three white squares one at a time, three uses are enough, which is optimal.
Choosing k=2 or greater would make it impossible to repaint Square 2, because of the restriction that does not allow the k squares to contain a blue square.

Samples2

Sample Input 2

13 3
13 3 9

Sample Output 2

6

Explaination

One optimal strategy is choosing k=2 and using the stamp as follows:

  • Repaint Squares 1,2 red.
  • Repaint Squares 4,5 red.
  • Repaint Squares 5,6 red.
  • Repaint Squares 7,8 red.
  • Repaint Squares 10,11 red.
  • Repaint Squares 11,12 red.

Note that, although the k consecutive squares chosen when using the stamp cannot contain blue squares, they can contain already red squares.

Samples3

Sample Input 3

5 5
5 2 1 4 3

Sample Output 3

0

Explaination

If there is no white square from the beginning, we do not have to use the stamp at all.

Samples4

Sample Input 4

1 0

Sample Output 4

1

Explaination

M may be 0.

Constraints

  • 1≤N≤10^9
  • 0≤M≤2×10^5
  • 1≤Ai≤N
  • Ai are pairwise distinct.
  • All values in input are integers.

题解报告

题目翻译

我们有 N 个正方形,从左到右排列。其中 M 个正方形已经被涂为红色,记为 A1, A2, ..., AM。剩下的都是白色。M 可以为零。

我们要选择一个正整数 k,我们可以将连续 k 个白色正方形涂成红色,注意已经涂成红色的可以重复上色。只允许对白色正方形涂成红色。请找出做少的涂色次数。

题目分析

又是一个模拟题。这次的 D 题有点水。我们先分析一下数据,然后再说伪码。

样例数据分析

样例数据 1

根据样例数据,我们可以绘制出如下图片。

如上图所示,一共 5 个正方形,编号为 1 ~ 5,其中 1 和 3 被涂成蓝色,我们需要将剩下的白色正方形涂成红色。上图有两块连续白色区域,第一个区域长度为 1,第二个区域长度为 2。由于不能将蓝色正方形涂成红色,我们只能选择最小的长度 k=1。这样涂色的过程如下:

第一次。将 2 号正方形涂成红色。

第二次。将 4 号正方形涂成红色。

第三次。将 5 号正方形涂成红色。

样例数据 2

根据样例数据,我们可以绘制出如下图片。

如上图所示,一共 13 个正方形,编号为 1 ~ 13,其中 3、9 和 13 被涂成蓝色,我们需要将剩下的白色正方形涂成红色。上图有三块连续白色区域,第一个区域长度为 2,第二个区域长度为 5,第二个区域长度为 3。由于不能将蓝色正方形涂成红色,我们只能选择最小的长度 k=2。这样涂色的过程如下:

第一次。将 1、2 号正方形涂成红色。

第二次。将 4、5 号正方形涂成红色。

第三次。将 6、7 号正方形涂成红色。

第四次。将 7、8 号正方形涂成红色。注意这里按照规则,将 7 号重复涂色。

第五次。将 10、11 号正方形涂成红色。

第六次。将 11、12 号正方形涂成红色。注意这里按照规则,将 11 号重复涂色。

样例数据 3

根据样例数据,我们可以绘制出如下图片。

如上图所示,一共 5 个正方形,编号为 1 ~ 5,所有正方形都被涂成蓝色。因此答案为 0。

样例数据 4

根据样例数据,我们可以绘制出如下图片。

如上图所示,一共 1 个正方形,编号为 1。其中没有正方形涂成蓝色,我们需要将剩下的白色正方形涂成红色。上图有一块连续白色区域,第一个区域长度为 1。我们只能选择最小的长度 k=1。这样涂色的过程如下:

第一次。将 1 号正方形涂成红色。

算法设计

从上面的样例数据分析,我们可以看出重点是要找到这个最小的 K。

细节

1、由于样例数据没有保证排序,参考样例 2 和样例 3,我们需要将输入的 A 进行排序。

2、通过遍历排序后的 A,我们可以得到 gap 数组,表示每个连续白色快长度。

3、找出 K。通过遍历 gap 数组,找出 gap 数组的非零最小值即可。

4、计算涂色的次数。我们可以遍历 gap 数组,计算 gap[i] 和 k 的关系。

伪码

读取n,m
读取数组 A
排序数组 A
遍历数据 A,计算间隔数组 gap
遍历数据 gap,找到最小非零 k
遍历数据 gap,计算 ans

AC 参考代码

//https://atcoder.jp/contests/abc185/tasks/abc185_d
//D - Stamp
#include <bits/stdc++.h>

using namespace std;

//如果提交到OJ,不要定义 __LOCAL
//#define __LOCAL

const int MAXN=1e9+4;
const int MAXM=2e5+4;
int a[MAXM];
int gap[MAXM];

int main() {
#ifndef __LOCAL
    //这部分代码需要提交到OJ,本地调试不使用
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    int n, m;
    cin>>n>>m;
    for (int i=1; i<=m; i++) {
        cin>>a[i];
    }
    a[m+1]=n+1;
    sort(a+1, a+m+1);

    //差分
    int k=MAXN;
    int ans=0;
    for (int i=1; i<=m+1; i++) {
        gap[i]=a[i]-a[i-1]-1;
        if (gap[i]<k && gap[i]>0) {
            k=gap[i];
        }
    }
    if (MAXN!=k) {
        for (int i=1; i<=m+1; i++) {
            ans += ceil(1.0*gap[i]/k);
        }
    }
    cout<<ans<<"\n";

#ifdef __LOCAL
    //这部分代码不需要提交到OJ,本地调试使用
    system("pause");
#endif
    return 0;
}

效率不是很高。再准备期末考试的间隙,防止老年痴呆,先将就一下。

时间复杂度

O(MlogM)。注意我们有一个排序,这个时间复杂度最高。

空间复杂度

O(M)。

猜你喜欢

转载自blog.csdn.net/justidle/article/details/111286992