目录
题目传送门
[CSP-J2020] 直播获奖 - 洛谷https://www.luogu.com.cn/problem/P7072
50分算法
算法
这道题呢,有一种很容易想到的算法,那就是每次输入都排一下序,然后输出第 max(1, p * w%) 名就可以了
可以用 STL 的排序 sort,也可以手写冒泡等排序(如选择、快排等)
这里呢,因为我很懒 sort 更加简洁,所以我用了 sort
注意,sort 需要算法头文件
#include <algorithm>
代码
这个程序很好写,这里就直接给大家贴代码
注意,需要判断 p * w% 是否是 0,如果是,则输出第一名
#include <iostream>
#include <algorithm>
#define N 100005
using namespace std;
int n, w, a[N];
bool cmp(int a, int b) {
return a > b;
}
int main() {
cin >> n >> w;
for(int p = 1; p <= n; ++p) {
cin >> a[p];
sort(a + 1, a + 1 + p, cmp);
if(p * w / 100 == 0)
cout << a[1] << " ";
else
cout << a[p * w / 100] << " ";
}
return 0;
}
提交结果
这可是 CSP-J 2020 年 T2 啊,怎么可能就这么简单呢?
可想而知,这玩意儿时间复杂度 O(n ^ 2 log n),一定 TLE
AC算法
算法
我们观察一下题目数据的值域
注意到“每个选手的成绩均为不超过 600 的非负整数”,这个数还蛮小的嘛,我们貌似可以用桶排把他们都存起来
int a[605];
这里,a[i] 表示成绩为 i 的人有多少个
可以用 m 来表示还需要多少名
从当前最大的成绩开始往前遍历,每次 m -= a[i](即每次还剩的人数减掉本次遍历到的成绩的人数),看什么时候还剩的人数 ≤ 0(即不剩下人了),当前这次遍历到的成绩(i)就是最终的答案
注意,需要判断 p * w% 是否等于 0,如果是,则找第一个(即 m = 1)
for(int p = 1; p <= n; ++p) {
cin >> x;
maxx = max(maxx, x);
++a[x];
m = p * w / 100;
if(m == 0)
m = 1;
for(int i = maxx; i >= 0; --i) {
m -= a[i];
if(m <= 0) {
cout << i << " ";
break;
}
}
}
代码
最终的 AC 代码:
#include <iostream>
#include <algorithm>
#define N 100005
using namespace std;
int n, w, x, a[N], maxx, m;
int main() {
cin >> n >> w;
for(int p = 1; p <= n; ++p) {
cin >> x;
maxx = max(maxx, x);
++a[x];
m = p * w / 100;
if(m == 0)
m = 1;
for(int i = maxx; i >= 0; --i) {
m -= a[i];
if(m <= 0) {
cout << i << " ";
break;
}
}
}
return 0;
}
提交结果
我们提交一下~
AC!!!
尾声
如果这篇题解对您(您的团队)有帮助的话,就帮忙点个赞,加个关注!
最后,祝您(您的团队)在 OI 的路上一路顺风!!!
┬┴┬┴┤・ω・)ノ Bye~Bye~