P1897 电梯里的爱情 [洛谷]
1.题目
题目描述
细心的同事发现,小 W 最近喜欢乘电梯上上下下,究其原因,也许只有小W自己知道:在电梯里经常可以遇到他心中的女神 PR。
电梯其实是个很暧昧的地方,只有在电梯里,小 W 才有勇气如此近距离接近女神,虽然觉得有点不自在,但次数多了,女神也习惯了小 W 的存在,甚至熟悉到仿佛不说上句话自己也都觉得不合适了。可是,他们的谈话也仅仅限于今天天气不错啊或是你吃了吗之类的,往往在对方微笑点头后就再次陷入难堪的沉默之中。 于是,小 W 便在陪伴女神的同时,也关注着电梯中显示的楼层数字,并且他注意到电梯每向上运行一层需要 6 6 6 秒钟,向下运行一层需要 4 4 4 秒钟,每开门一次需要 5 5 5 秒(如果有人到达才开门),并且每下一个人需要加 1 1 1 秒。
特别指出,电梯最开始在 0 0 0 层,并且最后必须再回到 0 0 0 层才算一趟任务结束。假设在开始的时候已知电梯内的每个人要去的楼层,你能计算出完成本趟任务需要的总时间吗?
这是个很简单的问题,要知道,小 W 已经修炼到快速心算出结果的境界,现在你来编程试试吧!
输入格式
共
2
2
2 行
第
1
1
1 行,一个正整数
n
n
n,表示乘坐电梯的人数。
第
2
2
2 行,
n
n
n 个正整数,
a
i
a_{i}
ai 表示第
i
i
i 个人要去的楼层。
输出格式
仅 1 1 1 行,一个正整数,表示完成这趟任务需要的时间。
样例输入 #1
4
2 4 3 2
样例输出 #1
59
提示
对于 60 % 60\% 60% 的数据 0 < n < 1 0 4 0<n<10^4 0<n<104
对于 100 % 100\% 100% 的数据 0 < n < 1 0 5 0<n<10^5 0<n<105, 0 < a i ≤ 2 × 1 0 7 0<a_{i}\leq 2\times 10^7 0<ai≤2×107。
2.分析
总时间= 电梯上下运行 + 开门时间 + 上下时间
电梯上下运行 = max(层数)❌10
开门时间 = 不同层数 ❌ 5
上下时间 = 人数
[set挺合适的~不过最开始没想到]
3.代码
1. 70分 TLE
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> //find();
typedef vector <int> VI;
typedef long long LL;
int main()
{
int n;
scanf("%d", &n);
VI difs;
int maxn = 0;
for (int i = 0; i < n; ++i)
{
int t;
scanf("%d", &t);
maxn = max(maxn, t);
auto res = find(difs.begin(), difs.end(), t);
if (res == difs.end()) difs.push_back(t);
}
LL res = 10 * maxn + 5 * difs.size() + n;
printf("%lld", res);
return 0;
}
原因分析:
find函数,较为缓慢
2. AC vector、erase、sort、unique
前置知识:
erase()、unique()函数
#include <iostream>
using namespace std;
#include <algorithm> //sort
#include <vector> //vector
typedef long long LL;
typedef vector <int> VI;
//res只与maxn与difs.size()有关,则直接排序去重即可
int main()
{
int n;
scanf("%d", &n);
VI difs; //存储 不同的楼层个数
int maxn = 0;
for (int i = 0; i < n; i++)
{
int t;
scanf("%d", &t);
maxn = max(maxn, t);
difs.push_back(t);
}
sort(difs.begin(), difs.end()); //排序
difs.erase(unique(difs.begin(), difs.end()), difs.end()); //去重
LL res = 10 * maxn + 5 * difs.size() + n;
printf("%lld", res);
return 0;
}
3.priority_quque 优先队列 [方便获取最大值]
速度慢了很多,内存占用也挺多
#include <iostream>
using namespace std;
#include <queue> //priority_queue
#include <algorithm> //sort;
typedef priority_queue <int> PQI;
typedef long long LL;
PQI fls; //优先队列,默认大根堆,即最大值即为顶
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int ttime(int x)
{
int t = 5;
while (fls.top() == x && fls.size()) t++, fls.pop();
return t;
}
int main()
{
int n;
scanf("%d", &n);
//读入所有楼层
for (int i = 0; i < n; ++i) fls.push(read());
//上下楼运行时间
LL res = 10 * fls.top();
//开门+出门
while (fls.size()) res += ttime(fls.top());
printf("%lld", res);
return 0;
}
注:该方法调用时,在VS中会报 front called on empty vector 错误,具体原因是调用top()时,会调用front(),为空时,不可调用front()
4.set 集合
#include <iostream>
using namespace std;
#include <set>
set<int> fls;
int main()
{
int n;
scanf("%d", &n);
for(int i=0;i<n;++i)
{
int x;
scanf("%d", &x);
fls.insert(x);
}
//int maxn = *fls.rbegin();
//或者
int maxn = *(--fls.end());
int res = 10 * maxn + 5 * fls.size() + n; //最多1e7
printf("%d", res);
return 0;
}
注:set会自动排序、自动去重,同时注意如何取得set最后一个元素
4.总结
灵活运用 优先队列、set
5.更新日志
2022.8.6
欢迎交流、讨论、指正~
不正确、不理解之处欢迎评论留言~