AtCoder题解——HHKB Programming Contest 2020——C - Neq Min

题目相关

题目链接

HHKB Programming Contest 2020 C 题,https://atcoder.jp/contests/hhkb2020/tasks/hhkb2020_c

Problem Statement

Given is a number sequence of length N: p1,...,pN.

For each i=1,2,...,N, find the minimum non-negative integer that is not equal to any of the numbers p1,...,pi.

Input

Input is given from Standard Input in the following format:

N
P1 ... PN

Output

Print N lines in total.

The i-th line (1≤i≤N) should contain the minimum non-negative integer that is not equal to any of the numbers p1,...,pi.

Samples1

Sample Input 1

4
1 1 0 2

Sample Output 1

0
0
2
3

Explaination

  • The minimum non-negative integer that is not equal to p1=1 is 0.
  • The minimum non-negative integer that is not equal to any of p1=1,p2=1 is 0.
  • The minimum non-negative integer that is not equal to any of p1=1,p2=1,p3=0 is 2.
  • The minimum non-negative integer that is not equal to any of p1=1,p2=1,p3=0,p4=2 is 3.

Samples2

Sample Input 2

10
5 4 3 2 1 0 7 7 6 6

Sample Output 2

0
0
0
0
0
6
6
6
8
8

Constraints

  • 1≤N≤200,000
  • 0≤pi≤200,000
  • All values in input are integers.

题解报告

肝完一个难题,写个水题压压惊。

题目翻译

给一个长度为 N 的序列,记为 P1, P2, ..., PN。要求我们找序列第 i 个数列中,找出最小的非负数,而且这个数没有在 P1, P2, ..., Pi 中。

题目分析

AtCoder 的 C 题是一个玄学,有时候会很水,比如这次,考数据结构的知识点。

要找出最小的非零负数,而且这个数必须没有在 P1, P2, ..., Pi 列中出现。那就很简单了,自己记录一下出现的数据即可,也就是在出现的数据做标记,然后每个询问,查找第一个没有标记的就是答案了。

但是要注意,本题有 N 个查询,如果每次都是从 0 到 2e5 查询的话,数据量大,会出现 TLE 哦。因为你的复杂度是 O(N^2) 的。

简单优化一下就可以了。也就是记录上次找到的 ans,下一次查询,从上次 ans 位置开始查询即可。

当然,本题最简单的思路是使用 STL 的 set。也就是,每次读入一个数据,从 set 中将这个数据删除,每次的答案就是 set 的开始位置。

样例数据 2 分析

看不明白,我们来分析一下样例数据。样例数据 1 比较小,我们选择样例数据 2。

根据样例 2,我们可以知道 N=10,读入的数据次序为:5 4 3 2 1 0 7 7 6 6。

初始状态

我们可以定义一个 11 大小状态数组,注意一定要比 N 大,可以考虑一下为什么?我们用 0 表示没有出现,用 1 表示出现。那么这个数组的初始状态为:

f[0]=0;
f[1]=0;
f[2]=0;
f[3]=0;
f[4]=0;
f[5]=0;
f[6]=0;
f[7]=0;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

用 ans 表示上次回答,因此 ans 初始化也为 0。

第一个数据 5

读取数据为 5。这样我们先将 f[5] 设置为 1。这样状态数组变为:

f[0]=0;
f[1]=0;
f[2]=0;
f[3]=0;
f[4]=0;
f[5]=1;
f[6]=0;
f[7]=0;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=0。

第二个数据 4

读取数据为 4。这样我们先将 f[4] 设置为 1。这样状态数组变为:

f[0]=0;
f[1]=0;
f[2]=0;
f[3]=0;
f[4]=1;
f[5]=1;
f[6]=0;
f[7]=0;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=0。

第三个数据 3

读取数据为 3。这样我们先将 f[3] 设置为 1。这样状态数组变为:

f[0]=0;
f[1]=0;
f[2]=0;
f[3]=1;
f[4]=1;
f[5]=1;
f[6]=0;
f[7]=0;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=0。

第四个数据 2

读取数据为 2。这样我们先将 f[2] 设置为 1。这样状态数组变为:

f[0]=0;
f[1]=0;
f[2]=1;
f[3]=1;
f[4]=1;
f[5]=1;
f[6]=0;
f[7]=0;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=0。

第五个数据 1

读取数据为 1。这样我们先将 f[1] 设置为 1。这样状态数组变为:

f[0]=0;
f[1]=1;
f[2]=1;
f[3]=1;
f[4]=1;
f[5]=1;
f[6]=0;
f[7]=0;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=0。

第六个数据 0

读取数据为 0。这样我们先将 f[0] 设置为 1。这样状态数组变为:

f[0]=1;
f[1]=1;
f[2]=1;
f[3]=1;
f[4]=1;
f[5]=1;
f[6]=0;
f[7]=0;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=6。

第七个数据 7

读取数据为 7。这样我们先将 f[7] 设置为 1。这样状态数组变为:

f[0]=1;
f[1]=1;
f[2]=1;
f[3]=1;
f[4]=1;
f[5]=1;
f[6]=0;
f[7]=1;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=6。

第八个数据 7

读取数据为 7。这样我们先将 f[7] 设置为 1。这样状态数组变为:

f[0]=1;
f[1]=1;
f[2]=1;
f[3]=1;
f[4]=1;
f[5]=1;
f[6]=0;
f[7]=1;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=6。

第九个数据 7

读取数据为 6。这样我们先将 f[6] 设置为 1。这样状态数组变为:

f[0]=1;
f[1]=1;
f[2]=1;
f[3]=1;
f[4]=1;
f[5]=1;
f[6]=1;
f[7]=1;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=8。

第十个数据 6

读取数据为 6。这样我们先将 f[6] 设置为 1。这样状态数组变为:

f[0]=1;
f[1]=1;
f[2]=1;
f[3]=1;
f[4]=1;
f[5]=1;
f[6]=1;
f[7]=1;
f[8]=0;
f[9]=0;
f[10]=0;
f[11]=0;

我们从 f[ans] 开始查找第一个为零的数据,并更新 ans 的值。

这样,我们得到 ans=8。

这样我们就得到了最终输出结果。

AC 参考代码

注意一个细节,由于最大数据有 2e5,使用流式输入输出,一定要用快读,否则最后三个测试用例就是 TLE。

不要问为什么,因为我无聊,我测试过。

使用标记法

//https://atcoder.jp/contests/hhkb2020/tasks/hhkb2020_c
//HHKB Programming Contest 2020
//C - Neq Min
/*
使用标记法
*/
#include <iostream>
#include <set>

using namespace std;

const int MAXN=2e5+4;
bool f[MAXN];

int main() {
    //快读
    ios::sync_with_stdio(false);
    //cin.tie(0);

    int n;
    cin>>n;

    int x;
    int ans=0;
    for (int i=0; i<n; i++) {
        cin>>x;

        //设置标志
        f[x]=true;

        //查找
        while (true==f[ans]) {
            ans++;
        }

        cout<<ans<<"\n";
   }

    return 0;
}

使用 STL 的 set

//https://atcoder.jp/contests/hhkb2020/tasks/hhkb2020_c
//HHKB Programming Contest 2020
//C - Neq Min
/*
使用 STL set
先将 0 ~ 2e5 所有数据插入 set 中。
然后读取数据,有的数据,从 set 中删除。
*/
#include <iostream>
#include <set>

using namespace std;

const int MAXN=2e5+4;

int main() {
    //快读
    ios::sync_with_stdio(false);
    //cin.tie(0);

    //讲所有数据标记
    set<int> st;
    for (int i=0; i<=MAXN; i++) {
        st.insert(i);
    }

    int n;
    cin>>n;

    int x;
    for (int i=0; i<n; i++) {
        cin>>x;

        st.erase(x);
        cout<<*st.begin()<<"\n";
   }

    return 0;
}

我去,使用标志法的时间还快那么一丢丢。使用 STL 就是代码量少。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值