美团codeM之美团代金券
前天做了下美团的一个codeM比赛的资格赛,遇到一个题目挺有意思的,所以现在做一下总结。
题目描述
美团的每一个用户都有一个用户代金券的消费记录日志,每位用户都能购买若干种代金券,但是每一种代金券最多只能购买一张。如果现在手上已经有了一张某种的代金券,那么只有在消费完这张代金券之后才能再次购买同种代金券。每位用户的购买和消费记录都记录在日志文件中,字符I代表购买代金券,字符O代表消费代金券。现在由于系统出现故障,造成了日志文件的损坏,在这个文件中有些记录无法恢复,只能用字符?代替,现在需要你来检查这个日志文件中的记录是否是合理的,如果出现某些冲突则表示该日志文件出现错误。
例如在某位用户的消费记录日志中的记录是这样的:
I 1
O 1
代表用户首先购买了编号为1的代金券,然后又消费了该代金券,所以该日志文件是正确的。对于正确的日志文件我们输出-1。
如果消费记录是这样的:
I 1
I 1
O 1
因为用户重复购买了编号为1的代金券,这是不合理的,所以这个日志文件有问题,问题出现在第二行,所以我们应该输出2。
如果消费记录是这样的:
?
I 1
O 2
因为这个?是无法恢复的,所以可以看做是任何可能的记录,在这个例子中我们可以将它视为I 2,在这样的解释之下,这个日志文件是合理的,所以我们最终的输出是-1。
输入样例
首先我们需要输入一个m,表明这个日志文件的总的行数。之后就像上述的例子那样的输入。
2
I 1
O 1
3
I 1
I 1
O 1
3
?
I 1
O 2
4
I 1
?
O 1
O 1
输出样例
如果日志文件没有问题那么输出-1,如果有问题则输出最早出现问题的行数。
-1
2
-1
4
解题思路
当时没有想明白具体的逻辑,改了很久都没有过,今天问小崔才明白正确的解题思路。经过分析之后我们知道,输入?的时候是肯定不会有错误的,错误只能出现在I与O的某行。那么当输入为I number的时候我们需要检查我们是否已经拥有这张代金券,如果没有那么这条记录是没有问题的,如果已经购买了这张代金券我们就应该进一步的检查,看上一次编号为number的代金券是什么时候买的,如果在这之间有一个?那么我们可以将这个?作为一个O number的记录,这样也就不会产生错误了。同样当输入为O number的时候我们同样按照相同的思路进行处理,如果有问题我们就应该进一步检查上一个相同编号的消费记录在什么时候,在这段时间内是否有?,如果有?我们就可以进行合理解释,否则就是一个错误的消费记录。
解题代码
#include <cstdio>
#include <set>
#include <cstring>
using namespace std;
const int maxn = 100000+10;
int m, number;
char type;
int buy_time[maxn], sale_time[maxn];
bool coupon[maxn];
set<int> unsure;
set<int>::iterator idx;
int main() {
while (~scanf("%d", &m)) {
memset(buy_time, -1, sizeof(buy_time));
memset(sale_time, -1, sizeof(sale_time));
memset(coupon, false, sizeof(coupon));
unsure.clear();
int ans = -1;
for (int i = 1; i <= m; ++i) {
getchar();
scanf("%c", &type);
if (type == '?') {
unsure.insert(i);
} else {
scanf("%d", &number);
if (type == 'I') {
if (!coupon[number]) {
coupon[number] = true;
} else {
// 对处于上一个I与现在这个I之间的第一个?做一个处理,将它作为一个O使用
int preBuyTime = buy_time[number];
idx = unsure.lower_bound(preBuyTime); // 返回preBuyTime之后的第一个?的位置
if (idx != unsure.end()) {
unsure.erase(idx);
} else {
// 如果没有?可以用,那么就是错误情况了
if (ans == -1) {
ans = i;
}
}
}
buy_time[number] = i;
} else {
if (coupon[number]) {
coupon[number] = false;
} else {
// 对处于上一个O与现在这个O之间的第一个?做一个处理,将它作为一个I使用
int preSaleTime = sale_time[number];
idx = unsure.lower_bound(preSaleTime); // 返回preSaleTime之后的第一个?的位置
if (idx != unsure.end()) {
unsure.erase(idx);
} else {
// 如果没有?可以用,那么就是错误情况了
if (ans == -1) {
ans = i;
}
}
}
sale_time[number] = i;
}
}
}
printf("%d\n", ans);
}
return 0;
}
美团codeM之美团代金券的更多相关文章
- LOJ #6192. 「美团 CodeM 复赛」城市网络 (树上倍增)
#6192. 「美团 CodeM 复赛」城市网络 内存限制:64 MiB 时间限制:500 ms 标准输入输出 题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接 ...
- #6164. 「美团 CodeM 初赛 Round A」数列互质-莫队
#6164. 「美团 CodeM 初赛 Round A」数列互质 思路 : 对这个题来言,莫队可以 n*根号n 离线处理出各个数出现个的次数 ,同时可以得到每个次数出现的次数 , 但是还要处理有多少 ...
- LibreOJ #6192. 「美团 CodeM 复赛」城市网络
#6192. 「美团 CodeM 复赛」城市网络 内存限制:64 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: sqc 提交提交记录统计讨论测试数据 题目描 ...
- 美团 CodeM 复赛」城市网络
美团 CodeM 复赛」城市网络 内存限制:64 MiB时间限制:500 ms标准输入输出 题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接的连通图),首都为 11 ...
- [LOJ 6213]「美团 CodeM 决赛」radar
[LOJ 6213]「美团 CodeM 决赛」radar 题意 给定 \(n\) 个横坐标 \(x_i\) , 为它们选择一个不超过 \(y_i\) 的纵坐标 \(h_i\), 产生 \(c_ih_i ...
- LibreOJ #6191. 「美团 CodeM 复赛」配对游戏
二次联通门 : LibreOJ #6191. 「美团 CodeM 复赛」配对游戏 /* LibreOJ #6191. 「美团 CodeM 复赛」配对游戏 概率dp */ #include <cs ...
- LibreOJ #6212. 「美团 CodeM 决赛」melon
二次联通门 : LibreOJ #6212. 「美团 CodeM 决赛」melon /* LibreOJ #6212. 「美团 CodeM 决赛」melon MDZZ 这是决赛题?? */ #incl ...
- 「题解」「美团 CodeM 资格赛」跳格子
目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...
- 【¥200代金券、iPad等您来拿】 阿里云9大产品免费公测#10月9日-11月6日#
#10.09-11.06#200元代金券.iPad大奖, 9大产品评测活动! 亲爱的阿里云小伙伴们: 云产品的多样性(更多的云产品)也是让用户深度使用云计算的关键.今年阿里云产品线越来越丰富,小云搜罗 ...
随机推荐
- RabbitMQ入门:主题路由器(Topic Exchange)
上一篇博文中,我们使用direct exchange 代替了fanout exchange,这次我们来看下topic exchange. 一.Topic Exchange介绍 topic exchan ...
- centos7以上安装python3,一条命令搞定。
直接复制下面的命令就搞定 yum install python34 python34-pip python34-setuptools 使用方法: python3 ---.py pip3 install ...
- mysql 连接超时解决方案: 怎样修改默认超时时间
mysql数据库有一个wait_timeout的配置,默认值为28800(即8小时). 在默认配置不改变的情况下,如果连续8小时内都没有访问数据库的操作,再次访问mysql数据库的时候,mysql数据 ...
- AS的使用技巧
title: AS的使用技巧 date: 2016-04-01 23:34:11 tags: [AndroidStudio] categories: [Tool,IDE] --- 概述 本文记录如何使 ...
- Python之并发编程-协程
目录 一.介绍 二. yield.greenlet.gevent介绍 1.yield 2.greenlet 3.gevent 一.介绍 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutin ...
- Vue实现双向绑定的原理以及响应式数据
一.vue中的响应式属性 Vue中的数据实现响应式绑定 1.对象实现响应式: 是在初始化的时候利用definePrototype的定义set和get过滤器,在进行组件模板编译时实现water的监听搜集 ...
- a标签的href为空的问题
在表格里写一个a标签链接刷新表格的时候,没注意,把a标签的href设置为""空字符串,导致每次刷新表格之后会再刷新一次整体页面,找了很久都没发现问题出在哪里,最后无意之间,鼠标在一 ...
- bing词典vs有道词典对比测试报告——功能篇之细节与用户体验
之所以将细节与用户体验放在一起讨论,是因为两者是那么的密不可分.所谓“细节决定成败”,在细节上让用户感受方便.舒适.不费心而且温馨,多一些人文理念,多一些情怀,做出来的产品自然比其他呆板的产品更受欢迎 ...
- java BufferedWriter写数据不完全
package com.brucekun.keyword; import java.io.BufferedReader; import java.io.BufferedWriter; import j ...
- 2018软工实践—Beta冲刺(5)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Beta 冲鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调组内工作 协助数据库完善搭建 展示GitHub当日代码/文档签入记 ...