目录
std::ios::sync_with_stdio(false)的运用
C++中"str.find(i) != str.end()"和"str.find(i) = str.end()"
A - 唱歌比赛
Description
n(n≤100) 名同学参加歌唱比赛,并接受 m(m≤20) 名评委的评分,评分范围是0 到 10 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下 m−2 个评分的平均数。请问得分最高的同学分数是多少?评分保留2 位小数。
Input
第一行两个整数n,m。
接下来 n 行,每行各 m 个整数,表示得分。
Output
输出分数最高的同学的分数,保留两位小数。
Sample 1
Inputcopy | Outputcopy |
---|---|
7 6 4 7 2 6 10 7 0 5 0 10 3 10 2 6 8 4 3 6 6 3 6 7 5 8 5 9 3 3 8 1 5 9 9 3 2 0 5 8 0 4 1 10 | 6.00 |
代码
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
int a[105][25];
double maxf=-1;
while(n--){
int maxa=-1,mina=11;
int z=0;
double f=0;
for(int i=0;i<m;i++){
cin>>a[n][i];
maxa=max(a[n][i],maxa);
mina=min(a[n][i],mina); //去掉最大最小评分
}
for(int i=0;i<m;i++) z+=a[n][i];
z=z-maxa-mina;
//cout<<z<<endl;
f=1.0*z/(m-2); //平均分
//cout<<f<<endl;
maxf=max(maxf,f);
}
printf("%.2lf\n",maxf);
return 0;
}
B - 旗鼓相当的对手 - 加强版
Description
现有 N(N≤1000) 名同学参加了期末考试,并且获得了每名同学的信息:姓名(不超过 8 个字符的字符串,没有空格)、语文、数学、英语成绩(均为不超过 150 的自然数)。如果某对学生 <i,j> 的每一科成绩的分差都不大于 5,且总分分差不大于 10,那么这对学生就是“旗鼓相当的对手”。现在我们想知道这些同学中,哪些是“旗鼓相当的对手”?请输出他们的姓名。
所有人的姓名是按照字典序给出的,输出时也应该按照字典序输出所有对手组合。也就是说,这对组合的第一个名字的字典序应该小于第二个;如果两个组合中第一个名字不一样,则第一个名字字典序小的先输出;如果两个组合的第一个名字一样但第二个名字不同,则第二个名字字典序小的先输出。
Input
第一行输入一个正整数 N,表示学生个数。
第二行开始,往下 N 行,对于每一行首先先输入一个字符串表示学生姓名,再输入三个自然数表示语文、数学、英语的成绩。均用空格相隔。
Output
输出若干行,每行两个以空格隔开的字符串,表示一组旗鼓相当的对手。注意题目描述中的输出格式。
Sample 1
Inputcopy | Outputcopy |
---|---|
3 fafa 90 90 90 lxl 95 85 90 senpai 100 80 91 | fafa lxl lxl senpai |
Hint
数据保证,1≤N≤1000,姓名为长度不超过 88 的字符串,语文、数学、英语成绩均为不超过150 的自然数。
代码
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
struct student
{
char name[25];
int yuwen;
int shuxue;
int yingyu;
int sum;
}stu[1005];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>stu[i].name>>stu[i].yuwen>>stu[i].shuxue>>stu[i].yingyu;
stu[i].sum=stu[i].yuwen+stu[i].shuxue+stu[i].yingyu;
}
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(abs(stu[i].sum-stu[j].sum)<=10){
if(abs(stu[i].yuwen-stu[j].yuwen)<=5
&&abs(stu[i].shuxue-stu[j].shuxue)<=5
&&abs(stu[i].yingyu-stu[j].yingyu)<=5)
cout<<stu[i].name<<" "<<stu[j].name<<endl;
}
}
}
return 0;
}
C - 最厉害的学生
Description
现有 N 名同学参加了期末考试,并且获得了每名同学的信息:姓名(不超过 8 个字符的仅有英文小写字母的字符串)、语文、数学、英语成绩(均为不超过 150 的自然数)。总分最高的学生就是最厉害的,请输出最厉害的学生各项信息(姓名、各科成绩)。如果有多个总分相同的学生,输出靠前的那位。
Input
第一行输入一个正整数 N,表示学生个数。
第二行开始,往下 N 行,对于每一行首先先输入一个字符串表示学生姓名,再输入三个自然数表示语文、数学、英语的成绩。均用空格相隔。
Output
输出最厉害的学生。
Sample 1
Inputcopy | Outputcopy |
---|---|
3 senpai 114 51 4 lxl 114 10 23 fafa 51 42 60 | senpai 114 51 4 |
Hint
数据保证,1≤N≤1000,姓名为长度不超过 8 的字符串,语文、数学、英语成绩均为不超过 150 的自然数。
代码
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
struct student
{
char name[25];
int yuwen;
int shuxue;
int yingyu;
int sum;
}stu[1005];
int main()
{
int n;
cin>>n;
int maxsum=-1;
for(int i=0;i<n;i++){
cin>>stu[i].name>>stu[i].yuwen>>stu[i].shuxue>>stu[i].yingyu;
stu[i].sum=stu[i].yuwen+stu[i].shuxue+stu[i].yingyu;
maxsum=max(maxsum,stu[i].sum);
}
for(int i=0;i<n;i++){
if(stu[i].sum==maxsum){
cout<<stu[i].name<<" "<<stu[i].yuwen<<" "<<stu[i].shuxue<<" "<<stu[i].yingyu<<endl;
break;
}
}
return 0;
}
D - 不重复数字
Description
给定 n 个数,要求把其中重复的去掉,只保留第一次出现的数。
Input
本题有多组数据。
第一行一个整数 T,表示数据组数。
对于每组数据:
第一行一个整数 n。
第二行 n 个数,表示给定的数。
Output
对于每组数据,输出一行,为去重后剩下的数,两个数之间用一个空格隔开。
Sample 1
Inputcopy | Outputcopy |
---|---|
2 11 1 2 18 3 3 19 2 3 6 5 4 6 1 2 3 4 5 6 | 1 2 18 3 19 6 5 4 1 2 3 4 5 6 |
Hint
对于 30% 的数据,n≤100,给出的数 ∈[0,100]。
对于 60% 的数据,n≤10^4,给出的数∈[0,10^4]。
对于 100% 的数据,1≤T≤50,1≤n≤5×10^4,给出的数在 32 位有符号整数范围内。
代码
#include<set>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
//c++中cin,cout效率较低,而这段语句可节省时间
int t; cin >>t;
while (t--){
int n; cin >> n;
vector<int> ans;
set<int> s;
for (int i = 1 ; i <= n ; i++){
int x; cin >> x;
if (s.find(x) != s.end()) continue; //如果找到就返回,不执行下面语句
ans.push_back(x);
s.insert(x);
}
for (auto g : ans) cout << g << " ";
cout << endl;
}
return 0;
}
std::ios::sync_with_stdio(false)的运用
continue 的用法详解
C++中"str.find(i) != str.end()"和"str.find(i) = str.end()"
E - 培训
Description
某培训机构的学员有如下信息:
- 姓名(字符串)
- 年龄(周岁,整数)
- 去年 NOIP 成绩(整数,且保证是 55 的倍数)
经过为期一年的培训,所有同学的成绩都有所提高,提升了 20%(当然 NOIP 满分是 600 分,不能超过这个得分)。
输入学员信息,请设计一个结构体储存这些学生信息,并设计一个函数模拟培训过程,其参数是这样的结构体类型,返回同样的结构体类型,并输出学员信息。
Input
第一行输入一个正整数 n,表示学员个数。
第二行开始往下 n 行。每行首先是一个字符串表示学员姓名,再是一个整数表示学员年龄,再是一个整数为去年 NOIP 成绩。
Output
输出 n 行,每行首先输出一个字符串表示学生姓名,再往后两个整数,表示经过一年的培训后学员的年龄和他们今年的 NOIP 成绩。以空格隔开。
Sample 1
Inputcopy | Outputcopy |
---|---|
3 kkksc03 24 0 chen_zhe 14 400 nzhtl1477 18 590 | kkksc03 25 0 chen_zhe 15 480 nzhtl1477 19 600 |
Hint
数据保证,1≤n≤5。年龄为0∼100(含 0 与 100)的整数。成绩为 0∼600(含 0 与600)的 5 的整倍数。
代码
#include<iostream>
#include<algorithm>
using namespace std;
struct student
{
char name[25];
int age;
int noipused;
int noipnow;
}stu[8];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>stu[i].name>>stu[i].age>>stu[i].noipused;
stu[i].age++; //过一年长一岁
stu[i].noipnow=stu[i].noipused*1.2;
if(stu[i].noipnow>600) stu[i].noipnow=600; //每个人成绩提高
}
for(int i=0;i<n;i++){
cout<<stu[i].name<<" "<<stu[i].age<<" "<<stu[i].noipnow<<endl;
}
return 0;
}
F - Zone Selection
Description
在第五人格巅峰七阶及以上的排位赛中,需要进行区域选择。我们将在本题中形式化、推广化的解决区域选择问题。
在地图中,共有 n 台密码机,第 i 台密码机的坐标为 (xi,yi)。在推广化的游戏中,有 k 名求生者。每名求生者可以选择一台密码机作为其出生点,我们称被选择的密码机为 出生密码机。
监管者共有 T 个出生点可供选择。第 i 个可能的出生点坐标为 (xi,yi)。此时,由于“封禁”天赋的存在,离监管者最远的密码机将不能被破译。
如果多台密码机与监管者的距离相同且最远,“封禁”天赋将会封禁这几台密码机中标号最小的那一台。
请问在该 T 个出生点中,有多少出生点,可以使某一台 出生密码机 被封禁。
请注意:坐标点 (x1,y1) 与坐标点 (x2,y2) 之间的距离为 2+(x1−x2)^2+(y1−y2)^2。
Input
输入共 n+T+k+1 行。
输入的第一行为三个整数n,k,T。
接下来 n 行,每行两个整数 xi,yi,表示一台密码机的坐标。
接下来 k 行,每行两个整数 xi,yi,表示一名求生者选择出生密码机的坐标,保证该坐标在上面出现过。
接下来 T 行,每行两个整数 xi,yi,表示监管者的一个出生点。
Output
输出一行一个整数,为答案。
Sample 1
Inputcopy | Outputcopy |
---|---|
4 2 2 -1 0 0 -1 2 0 0 2 -1 0 0 2 3 0 0 0 | 1 |
Hint
【样例 #1 解释】
显然,第一台密码机和第四台密码机为出生密码机。
第一位监管者与位置在(−1,0) 的第一台密码机距离最远,为 4。因此,第一台密码机被封禁。
第二位监管者与位置在(2,0),(0,2) 的第三、四台密码机距离相同且最远,为 2。根据上面提到的规则,第三台密码机被封禁。
被封禁的出生密码机为 1 台。
【数据规模与约定】
对前 10% 的数据,保证n=k=1。
对前 20% 的数据,保证 n,k,t≤10。
对另外 20% 的数据,保证密码机与出生点的坐标中的 x 均为 0。
对另外 10% 的数据,保证 n=k。
对另外 10% 的数据,保证 T=1。
对于 100% 的数据范围 1≤k≤n≤10^3,1≤T≤10^3,1≤∣xi∣,∣yi∣≤10^3。
思路
记录各密码机,标记求生者选择的,判断被封禁的是否为被标记的
代码
#include<bits/stdc++.h>
using namespace std;
long long n, k, t, ans = 0;
struct point {
int x, y;
bool mark;
} a[1005];
double dist(int i, int j, int k1, int l) {
return sqrt(((i - k1) * (i - k1) + (j - l) * (j - l)) * 1.0);
} //距离
int main() {
cin >> n >> k >> t;
for (int i = 1; i <= n; i++)
cin >> a[i].x >> a[i].y; 密码机的坐标
for (int i = 1; i <= k; i++) {
int x, y;
cin >> x >> y;
for (int j = 1; j <= n; j++) {
if (x == a[j].x && y == a[j].y) {
a[j].mark = true;求生者选择出生密码机的坐标
break;
}
}
}
for (int i = 1; i <= t; i++) {
int x, y;
cin >> x >> y;
double max_d = -1;
int f = 0;
for (int j = 1; j <= n; j++) {
if (dist(x, y, a[j].x, a[j].y) > max_d) {
max_d = dist(x, y, a[j].x, a[j].y);
f = a[j].mark;出生密码机被封禁
}
}
if (f) ans++; //如果是求生者选择的出生密码机就记录
}
cout << ans;
return 0;
}
G - 演唱会
Description
一个特殊的节日,zyl 举办了一场演唱会,他想要规划一下演唱会的曲目。
根据同学的要求,他要从 n 首歌(编号 1∼n)中选出 m 首加入演唱会歌单。
选择的规则很简单,班上有 a 名学生(不包括 zyl),学号为 1∼a。zyl 会按照学号统计每位同学从每首歌中得到的快乐值,记为 hi,j。一首歌的「欢乐度」是它所给予其他所有同学的「快乐值」总和。
巧妙的是,由于歌曲风格迥异,同一个学生一定会从不同的歌中会收获不同的快乐值,且不会有任何两首歌的欢乐度相同。
zyl 选出欢乐度最高的 m 首歌,并将它们按欢乐度从大到小排好序。
但 zyl 注意到了她的快乐值…
无论如何,zyl 一定会把她最喜欢的歌放进歌单(她获得快乐值最高的歌即为她最喜欢的歌)!
如果她最喜欢的歌之前已经在歌单中,那么 zyl 会把这首歌提到歌单的第一个位置(即,仅将该歌曲的位置变为第一位,其余歌曲的相对位置不变);但如果不在,zyl 则会把已经选择好的歌单里的最后一首歌给删掉。然后把她最喜欢的曲目放在歌单的最后。
现在 zyl 将统计的快乐值数据和她的学号交给你,请你帮他列出演唱会的歌单。
Input
输入共 a+1 行。
第一行共四个整数 n,m,a,b,分别代表待选的歌的数量,需要选出的歌的数量,班上的人数,她的学号。
接下来 a 行,每行 n 个整数,第 i+1 行第 j 个数代表学号为 i 的学生从第 j 首歌收获的快乐值 hi,j。
Output
输出共一行用空格隔开的 m 个整数,依次代表演唱会的歌单上的歌的编号。
Sample 1
Inputcopy | Outputcopy |
---|---|
4 2 3 2 2 4 3 1 1 2 3 4 2 3 4 1 | 3 4 |
Hint
样例 1 解释
按照欢乐度排序后靠前的两道是 3,2,但由于她最喜欢的歌是 4,不在歌单里,于是将 2 从歌单里删除,之后将 4 放在最后。最后的歌单为 3,4。
数据规模与约定
对于 100% 的数据,1≤m≤n≤10^5,1≤b≤a≤100。0≤ℎ,0≤hi,j≤106。
测试点编号 | n | m | a | hi,j |
---|---|---|---|---|
1∼2 | ≤5 | =1 | ≤5 | ≤10000 |
3∼4 | ≤1000 | =n | ≤100 | ≤10000 |
5∼6 | ≤1000 | ≤1000 | =1 | ≤10000 |
7∼9 | ≤1000 | ≤1000 | ≤100 | ≤10000 |
10 | ≤10^5 | ≤10^5 | ≤100 | ≤10^6 |
代码
#include<bits/stdc++.h>
using namespace std;
struct song{
int id;//编号
int k;//快乐值
}h[100005];
bool cmp(song a,song b){
return a.k>b.k;//排序
}
int maxn,maxid;
int n,a,b,m;
int main(){
cin >> n >> m >> a >> b;
for(int i =1;i<=a;i++ ){
for(int j = 1;j<=n;j++){
int x;
scanf("%d",&x);
if(i==b){
if(x>maxn)maxn = x,maxid = j;//zyl最喜欢的歌
}
h[j].k+=x,h[j].id = j;//歌的快乐值及编号
}
}
sort(h+1,h+n+1,cmp);//快乐值排序
bool f=0;
for(int i = 1;i<=m;i++)if(h[i].id==maxid)f=1;
if(f==1){ //最喜欢歌在其中
cout <<maxid<<" ";
for(int i =1;i<=m;i++)if(h[i].id!=maxid)cout <<h[i].id<<" ";
}
else{//不再其中
for(int i = 1;i<m;i++)cout <<h[i].id<<" ";
cout <<maxid;
}
return 0;
}
H - BNA - PICK
Description
在第五人格职业联赛的每一场对局中,需要进行 Ban-Pick 流程。Ban 即角色禁用,Pick 即角色选用。
如试题 Winner 所述,游戏分为 求生者(SurvivorSurvivor) 与 监管者(HunterHunter) 两个阵营。求生者阵营 共有 n 名角色,监管者阵营 共有 m 名角色。
在某局比赛中,监管者 可以 ban(禁用) 掉 求生者阵营 5 名角色,求生者 可以 ban(禁用) 掉 监管者阵营 2 名角色。
每个角色,无论其属于求生者阵营还是监管者阵营,均可以使用 熟练度 来量化该阵营选手选择该角色的优先程度。选手一定会优先选择 熟练度 更高的角色进行游戏。
基于这样的考量,监管者选手 在进行 Ban 流程时,往往会选择 ban(禁用) 掉 求生者阵营熟练度最高 的若干名 求生者角色。同样,求生者选手 在进行 Ban 流程时,往往会选择 ban(禁用) 掉 监管者阵营熟练度最高 的若干名 监管者角色。
在 Ban 流程完成后,需要执行 Pick 流程。
如试题 Winner 所述,求生者选手 需要从 求生者阵营 中选择 4 名不同的角色,监管者选手 需要从 监管者阵营 中选择 1 名角色。
现在告诉你所有角色的名字、阵营与选手对其熟练度,请你给出双方阵营 Pick 的角色名字。
Input
输入共 1n+m+1 行。
输入的第一行为两个整数 n,m,分别代表求生者阵营角色数和监管者阵营角色数。
接下来n+m 行,首先为一个仅由英文字母组成的字符串,代表该角色的姓名;接下来为一个大写字符 H
或 S
,若为 H
,则代表该角色为监管者阵营,若为 S
,则代表该角色为求生者阵营;接下来一个正整数,代表该阵营选手对该角色的熟练度。上述字符串、大写字符、正整数之间由一个空格分隔。
Output
输出共 5 行。
输出的第一行为监管者阵营选择角色的角色名。
输出的第二到五行为求生者阵营选择角色的角色名,按照熟练度从高到低排列。
Sample 1
Inputcopy | Outputcopy |
---|---|
9 3 Amily S 1 Lydia S 2 Lisa S 4 Beck H 1 Freddie S 5 Cliche S 6 Aesop S 7 Eli S 8 Norton S 9 Tiletower H 3 Yidhra H 2 Emma S 3 | Beck Lisa Emma Lydia Amily |
Hint
输入输出样例 1 解释
求生者阵营角色:Amily,Lydia,Lisa,Freddie,Cliche,Aesop,Eli,Norton,Emma
监管者阵营角色:Beck,Tiletower,Yidhra
监管者选手将 ban 掉求生者阵营中角色 Norton,Eli,Aesop,Cliche,Freddie
求生者选手将 ban 掉监管者阵营中角色 Tiletower,Yidhra
思路
监管者 可以 ban(禁用) 掉 求生者阵营 5 名角色,求生者 可以 ban(禁用) 掉 监管者阵营 2 名角色,求生者选手 需要从 求生者阵营 中选择 4 名不同的角色,监管者选手 需要从 监管者阵营 中选择 1 名角色,被ban(禁用) 或被选都是 熟练度最高的。
所以,直接输出熟练度排名为 监管者阵营·3和求生者阵营·6-9 就可以
代码
#include<bits/stdc++.h>
using namespace std;
struct node {
string name; //求生者与监管者名
long long val; //熟练度
} s[100005], h[100005];
int cmp(node x, node y) {
return x.val > y.val;
} //熟练度排序
int n,m;
signed main(){
int cntH = 0, cntS = 0;
cin >> n >> m;
for (int i = 1; i <= n + m; ++i) {
string name, v;
long long val;
cin >> name >> v >> val;
if (v == "H") { //判断阵营为监管者
++cntH;
h[cntH].name = name;
h[cntH].val = val;
}
else { //求生者阵营
++cntS;
s[cntS].name = name;
s[cntS].val = val;
}
}
sort(s + 1, s + cntS + 1, cmp);
sort(h + 1, h + cntH + 1, cmp);
cout << h[3].name << endl;
for (int i = 6; i <= 9; ++i) {
cout << s[i].name << endl;
}
}