【牛客小白月赛22】NC202474 操作序列

操作序列

https://ac.nowcoder.com/acm/contest/4462/A

这是一道挺不错的STL模拟题,做法也很多,可以借此巩固一下对STL的知识运用

由于数列长度无限,所以我们需要离散化,可以用一个容器(如map,set,建议先了解一下它们的用法及基本的指针用法)存储不为0的数及它的下标

  • 增加操作:给下标为 tt 的数加 cc 。特别注意,如果在下标 [t-30,t+30] 内有不为零的数,增加操作无效。
    【对于下标 [t-30,t+30] 内,可以直接枚举扫一遍,还可以用lower_bound查询下标>=t-30的第一个数,然后判断它的下标是否<=t+30】

  • 削减操作:让数列中下标最小的不为零数变为零。
    【如果容器中有数变为0了,我们就直接erase把它去除,让容器中只存储不为0的数,这样数列中下标最小的不为零数就是容器中的第一个数了,用begin即可操作】

  • 查询操作:查询数列中下标为 tt 的数字是多少。
    【分两种情况,下标tt上可能没有数字,即为0,不在我们的容器当中,所以我们首先要用lower_bound或(map)count来查询这个数是否在容器中再输出】

对于每个操作,可能是一个数也可能是两个数,其实我们不用字符串读入,不管用什么容器都可以用下面的模板

#include<cstdio>
using namespace std;
map<int,int> a;
int main(){
    int n;
    scanf("%d",&n);
    for (int t,c;n;n--){
        scanf("%d",&t);//先读入第一个数
        if (getchar()=='\n'){//下一个字符是换行符吗?(如果有第二个数则getchar()读入的是空格,如果是换行符说明只有一个数)
            if (t==-1){
               //削减操作
            }
            else {
               //查询操作
            }
        }else{
           //增加操作
        }
    }
}

小提示:

  • auto可以自动推导变量类型,编译器根据初始化表达式(根据“=”右侧的变量类型)来自动推导变量类型,在代码中代替迭代器类型写起来比较简便,不过有些C++上可能用不了(牛客上的C++可以)
  • lower_bound(val)返回大于或等于val的第一个元素位置。如果查询不到,则返回end()

方法一:map

#include<cstdio>
#include<map>
using namespace std;
map<int,int> a;//二元组分别是坐标和对应的数
int main(){
    int n;
    scanf("%d",&n);
    for (int t,c;n;n--){
        scanf("%d",&t);
        if (getchar()=='\n'){
            if (t==-1){
                if (a.empty()) puts("skipped");//没有不为0的数了
                else printf("%d\n",a.begin()->second),a.erase(a.begin());//输出第一个二元组存储的数并把它删去(变为0)
            }
            else {
                if (a.count(t)) printf("%d\n",a[t]);//count查询是否有坐标为t
                else puts("0");
            }
        }else{
            scanf("%d",&c);
            auto pos=a.lower_bound(t-30);//这里的auto相当于map<int,int>::iterator
            if (pos==a.end() || pos->first>t+30) a[t]=c;//如果[t-30,t+30]没有不为0的数
        }
    }
}

方法二:set

#include<cstdio>
#include<set>
using namespace std;
set<pair<int,int> > a;
pair<int,int> tmp;
int main(){
    int n;
    scanf("%d",&n);
    for (int t,c;n;n--){
        scanf("%d",&t);
        if (getchar()=='\n'){
            if (t==-1){
                if (a.empty()) puts("skipped");//没有不为0的数了
                else {
                    printf("%d\n",(*a.begin()).second);//输出第一个二元组存储的数
                    a.erase(a.begin());//把它删去(变为0)
                }
            }
            else {
                tmp.first=t;
                auto pos=a.lower_bound(tmp);//查询是否有二元组坐标为t,这里的auto相当于set<pair<int,int> >::iterator
                if(pos==a.end() || (*pos).first!=t) puts("0");
                else printf("%d\n",(*pos).second);
            }
        }else{
            scanf("%d",&c);
            tmp.first=t-30;
            auto pos=a.lower_bound(tmp);//这里的auto相当于set<pair<int,int> >::iterator
            if(pos==a.end() || (*pos).first>t+30) a.insert(make_pair(t,c));//如果[t-30,t+30]没有不为0的数,则在容器中加入新数字及下标
        }
    }
}

方法三:据出题者说除此之外还“可以离线下来胡搞,也可以平衡树在线”,由于作者能力有限,就留给dalao去探索吧qwq

如果题解中有什么错误或可以改进的地方,还望大家在评论区指出qwq!

全部评论
为什么 if (a.count(t)) printf("%d\n",a[t]);//count查询是否有坐标为t else puts("0");这个不能直接写成printf("%d\n",a[t]).如果没有不也是为0嘛,为什么会wa
点赞 回复 分享
发布于 2020-04-08 18:06
能问一下这些具体的stl知识,你是哪里知道的嘛
点赞 回复 分享
发布于 2020-04-08 17:02
@Boops 你好,看到了你的回复,的确下标很大的情况可能爆int,但是由于本题数据较水int可过,如果有下标很大的数据的话用long long甚至字符串存储下标应该可以过
点赞 回复 分享
发布于 2020-02-25 11:39

相关推荐

05-09 12:23
已编辑
华南理工大学 Java
野猪不是猪🐗:给他装的,双九+有实习的能看的上这种厂我直接吃⑨✌们拿它练练面试愣是给他整出幻觉了
点赞 评论 收藏
分享
05-11 11:48
河南大学 Java
程序员牛肉:我是26届的双非。目前有两段实习经历,大三上去的美团,现在来字节了,做的是国际电商的营销业务。希望我的经历对你有用。 1.好好做你的CSDN,最好是直接转微信公众号。因为这本质上是一个很好的展示自己技术热情的证据。我当时也是烂大街项目(网盘+鱼皮的一个项目)+零实习去面试美团,但是当时我的CSDN阅读量超百万,微信公众号阅读量40万。面试的时候面试官就告诉我说觉得我对技术挺有激情的。可以看看我主页的美团面试面经。 因此花点时间好好做这个知识分享,最好是单拉出来搞一个板块。各大公司都极其看中知识落地的能力。 可以看看我的简历对于博客的描述。这个帖子里面有:https://www.nowcoder.com/discuss/745348200596324352?sourceSSR=users 2.实习经历有一些东西删除了,目前看来你的产出其实很少。有些内容其实很扯淡,最好不要保留。有一些点你可能觉得很牛逼,但是面试官眼里是减分的。 你还能负责数据库表的设计?这个公司得垃圾成啥样子,才能让一个实习生介入数据库表的设计,不要写这种东西。 一个公司的财务审批系统应该是很稳定的吧?为什么你去了才有RBAC权限设计?那这个公司之前是怎么处理权限分离的?这些东西看着都有点扯淡了。 还有就是使用Redis实现轻量级的消息队列?那为什么这一块不使用专业的MQ呢?为什么要使用redis,这些一定要清楚, 就目前看来,其实你的这个实习技术还不错。不要太焦虑。就是有一些内容有点虚了。可以考虑从PR中再投一点产出
点赞 评论 收藏
分享
评论
4
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务