P1583 魔法照片
题目描述
一共有n(n≤20000)个人(以1--n编号)向佳佳要照片,而佳佳只能把照片给其中的k个人。佳佳按照与他们的关系好坏的程度给每个人赋予了一个初始权值W[i]。然后将初始权值从大到小进行排序,每人就有了一个序号D[i](取值同样是1--n)。按照这个序号对10取模的值将这些人分为10类。也就是说定义每个人的类别序号C[i]的值为(D[i]-1) mod 10 +1,显然类别序号的取值为1--10。第i类的人将会额外得到E[i]的权值。你需要做的就是求出加上额外权值以后,最终的权值最大的k个人,并输出他们的编号。在排序中,如果两人的W[i]相同,编号小的优先。
输入输出格式
输入格式:
第一行输入用空格隔开的两个整数,分别是n和k。
第二行给出了10个正整数,分别是E[1]到E[10]。
第三行给出了n个正整数,第i个数表示编号为i的人的权值W[i]。
输出格式:
只需输出一行用空格隔开的k个整数,分别表示最终的W[i]从高到低的人的编号。
输入输出样例
10 10 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20
10 9 8 7 6 5 4 3 2 1
1 #include<bits/stdc++.h> 2 using namespace std; 3 int e[12],n,k; 4 struct person{ 5 int w; 6 int num; 7 int d; 8 }p[20010]; 9 int w_comp(const person &a,const person &b){ 10 if(a.w!=b.w)return a.w>b.w; 11 return a.num<b.num; 12 } 13 int main(){ 14 scanf("%d%d",&n,&k); 15 for(int i=0;i<10;i++)scanf("%d",&e[i]); 16 for(int i=0;i<n;i++){ 17 scanf("%d",&p[i].w); 18 p[i].num=i+1; 19 } 20 sort(p,p+n,w_comp); 21 for(int i=0;i<n;i++){ 22 p[i].d=i%10; 23 p[i].w+=e[p[i].d]; 24 } 25 sort(p,p+n,w_comp); 26 for(int i=0;i<k;i++)printf("%d ",p[i].num); 27 }
P1051 谁拿了最多奖学金
题目描述
某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同:
- 院士奖学金,每人 80008000 元,期末平均成绩高于 8080 分( >80>80 ),并且在本学期内发表 11 篇或 11 篇以上论文的学生均可获得;
- 五四奖学金,每人 40004000 元,期末平均成绩高于 8585 分( >85>85 ),并且班级评议成绩高于 8080 分( >80>80 )的学生均可获得;
- 成绩优秀奖,每人 20002000 元,期末平均成绩高于 9090 分( >90>90 )的学生均可获得;
- 西部奖学金,每人 10001000 元,期末平均成绩高于 8585 分( >85>85 )的西部省份学生均可获得;
- 班级贡献奖,每人 850850 元,班级评议成绩高于 8080 分( >80>80 )的学生干部均可获得;
只要符合条件就可以得奖,每项奖学金的获奖人数没有限制,每名学生也可以同时获得多项奖学金。例如姚林的期末平均成绩是 8787 分,班级评议成绩 8282 分,同时他还是一位学生干部,那么他可以同时获得五四奖学金和班级贡献奖,奖金总数是 48504850 元。
现在给出若干学生的相关数据,请计算哪些同学获得的奖金总数最高(假设总有同学能满足获得奖学金的条件)。
输入输出格式
输入格式:
第一行是 11 个整数 N(1 \le N \le 100)N(1≤N≤100) ,表示学生的总数。
接下来的 NN 行每行是一位学生的数据,从左向右依次是姓名,期末平均成绩,班级评议成绩,是否是学生干部,是否是西部省份学生,以及发表的论文数。姓名是由大小写英文字母组成的长度不超过 2020 的字符串(不含空格);期末平均成绩和班级评议成绩都是 00 到 100100 之间的整数(包括 00 和 100100 );是否是学生干部和是否是西部省份学生分别用 11 个字符表示, YY 表示是, NN 表示不是;发表的论文数是 00 到 1010 的整数(包括 00 和 1010)。每两个相邻数据项之间用一个空格分隔。
输出格式:
包括 33 行。
第 11 行是获得最多奖金的学生的姓名。
第 22 行是这名学生获得的奖金总数。如果有两位或两位以上的学生获得的奖金最多,输出他们之中在输入文件中出现最早的学生的姓名。
第 33 行是这 NN 个学生获得的奖学金的总数。
输入输出样例
4 YaoLin 87 82 Y N 0 ChenRuiyi 88 78 N Y 1 LiXin 92 88 N N 0 ZhangQin 83 87 Y N 1
ChenRuiyi 9000 28700
说明
2005提高组第一题
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct p{ 4 char s[25]; 5 int i; 6 int qimo_grade; 7 int class_grade; 8 char c,c1; 9 int num; 10 int sum; 11 p(){ 12 sum=0; 13 } 14 }a[105]; 15 bool cmp(p x,p y); 16 int main(){ 17 int n; 18 scanf("%d",&n); 19 int sum=0; 20 for(int i=0;i<n;i++){ 21 scanf("%s %d %d %c %c %d",a[i].s,&a[i].qimo_grade,&a[i].class_grade,&a[i].c,&a[i].c1,&a[i].num); 22 a[i].i=i; 23 if(a[i].qimo_grade>80&&a[i].num>=1) a[i].sum+=8000; 24 if(a[i].qimo_grade>85&&a[i].class_grade>80) a[i].sum+=4000; 25 if(a[i].qimo_grade>90) a[i].sum+=2000; 26 if(a[i].qimo_grade>85&&a[i].c1=='Y') a[i].sum+=1000; 27 if(a[i].class_grade>80&&a[i].c=='Y') a[i].sum+=850; 28 sum+=a[i].sum; 29 } 30 sort(a,a+n,cmp); 31 printf("%s\n%d\n%d\n",a[0].s,a[0].sum,sum); 32 } 33 bool cmp(p x,p y){ 34 if(x.sum!=y.sum)return x.sum>y.sum; 35 return x.i<y.i; 36 }
P1093 奖学金
1 题目描述 2 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学 排在前面,这样,每个学生的排序是唯一确定的。 3 4 任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前五名名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分) 是: 5 6 77 279279 7 55 279279 8 9 这两行数据的含义是:总分最高的两个同学的学号依次是 77 号、 55 号。这两名同学的总分都是 279279 (总分等于输入的语文、数学、英语三科成绩之和) ,但学号为 77 的学生语文成绩更高一些。如果你的前两名的输出数据是: 10 11 55 279279 12 77 279279 13 14 则按输出错误处理,不能得分。 15 16 输入输出格式 17 输入格式: 18 共n+1行。 19 20 第 11 行为一个正整数 n( \le 300)n(≤300) ,表示该校参加评选的学生人数。 21 22 第 22 到 n+1n+1 行,每行有 33 个用空格隔开的数字,每个数字都在 00 到 100100 之间。第 jj 行的 33 个数字依次表示学号为 j-1j−1 的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为 1~n1 n (恰好是输入数据的行号减 11 )。 23 24 所给的数据都是正确的,不必检验。 25 26 //感谢 黄小U饮品 修正输入格式 27 28 输出格式: 29 共5行,每行是两个用空格隔开的正整数,依次表示前 55 名学生的学号和总分。 30 31 输入输出样例 32 输入样例#1: 复制 33 6 34 90 67 80 35 87 66 91 36 78 89 91 37 88 99 77 38 67 89 64 39 78 89 98 40 输出样例#1: 复制 41 6 265 42 4 264 43 3 258 44 2 244 45 1 237 46 47 输入样例#2: 复制 48 8 49 80 89 89 50 88 98 78 51 90 67 80 52 87 66 91 53 78 89 91 54 88 99 77 55 67 89 64 56 78 89 98 57 输出样例#2: 复制 58 8 265 59 2 264 60 6 264 61 1 258 62 5 258
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct p{ 4 int i; 5 int yu,sum; 6 }a[305]; 7 bool cmp(p x,p y); 8 int main(){ 9 int n; 10 scanf("%d",&n); 11 for(int i=0;i<n;i++){ 12 int x,y,z; 13 scanf("%d%d%d",&x,&y,&z); 14 a[i].i=i+1;a[i].yu=x;a[i].sum=x+y+z; 15 } 16 sort(a,a+n,cmp); 17 for(int i=0;i<5;i++){ 18 if(i>=n) break; 19 printf("%d %d\n",a[i].i,a[i].sum); 20 } 21 } 22 bool cmp(p x,p y){ 23 if(x.sum!=y.sum) return x.sum>y.sum; 24 else if(x.yu!=y.yu) return x.yu>y.yu; 25 return x.i<y.i; 26 }
P1309 瑞士轮
题目背景
在双人对决的竞技性比赛,如乒乓球、羽毛球、国际象棋中,最常见的赛制是淘汰赛和循环赛。前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高。后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长。
本题中介绍的瑞士轮赛制,因最早使用于 18951895 年在瑞士举办的国际象棋比赛而得名。它可以看作是淘汰赛与循环赛的折中,既保证了比赛的稳定性,又能使赛程不至于过长。
题目描述
2 \times N2×N 名编号为 1-2N1−2N 的选手共进行R 轮比赛。每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名。选手的总分为第一轮开始前的初始分数加上已参加过的所有比赛的得分和。总分相同的,约定编号较小的选手排名靠前。
每轮比赛的对阵安排与该轮比赛开始前的排名有关:第 11 名和第 22 名、第 33 名和第 44 名、……、第 2K - 12K−1 名和第 2K2K 名、…… 、第 2N - 12N−1 名和第 2N2N 名,各进行一场比赛。每场比赛胜者得 11 分,负者得 00 分。也就是说除了首轮以外,其它轮比赛的安排均不能事先确定,而是要取决于选手在之前比赛中的表现。
现给定每个选手的初始分数及其实力值,试计算在R 轮比赛过后,排名第 QQ 的选手编号是多少。我们假设选手的实力值两两不同,且每场比赛中实力值较高的总能获胜。
输入输出格式
输入格式:
第一行是三个正整数 N,R ,QN,R,Q ,每两个数之间用一个空格隔开,表示有 2 \times N2×N 名选手、 RR 轮比赛,以及我们关心的名次 QQ 。
第二行是 2 \times N2×N 个非负整数 s_1, s_2, …, s_{2N}s1,s2,…,s2N ,每两个数之间用一个空格隔开,其中 s_isi 表示编号为 ii 的选手的初始分数。 第三行是 2 \times N2×N 个正整数 w_1 , w_2 , …, w_{2N}w1,w2,…,w2N ,每两个数之间用一个空格隔开,其中 w_iwi 表示编号为 ii 的选手的实力值。
输出格式:
一个整数,即 RR 轮比赛结束后,排名第 QQ 的选手的编号。
输入输出样例
说明
【样例解释】
【数据范围】
对于 30\%30% 的数据, 1 ≤ N ≤ 1001≤N≤100 ;
对于 50\%50% 的数据, 1 ≤ N ≤ 10,0001≤N≤10,000 ;
对于 100\%100% 的数据, 1 ≤ N ≤ 100,000,1 ≤ R ≤ 50,1 ≤ Q ≤ 2N,0 ≤ s_1, s_2, …, s_{2N}≤10^8,1 ≤w_1, w_2 , …, w_{2N}≤ 10^81≤N≤100,000,1≤R≤50,1≤Q≤2N,0≤s1,s2,…,s2N≤108,1≤w1,w2,…,w2N≤108。
noip2011普及组第3题。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define maxn 200001 4 typedef struct Node{ 5 int grade; 6 int num; 7 }Node; 8 Node a[maxn]; 9 Node A[100001]; 10 Node B[100001]; 11 int w[maxn]; 12 bool cmp(Node a,Node b) 13 { 14 if(a.grade == b.grade) 15 return a.num<b.num; 16 return a.grade>b.grade; 17 } 18 int n,r,q; 19 void MergeSort() 20 { 21 int i=1,j=1,k=1; 22 while(i<=n && j<=n) 23 { 24 if(A[i].grade > B[j].grade || (A[i].grade == B[j].grade && A[i].num < B[j].num)) 25 { 26 a[k].grade = A[i].grade; 27 a[k++].num = A[i++].num; 28 } 29 else{ 30 a[k].grade = B[j].grade; 31 a[k++].num = B[j++].num; 32 } 33 } 34 while(i<=n) 35 { 36 a[k].grade = A[i].grade; 37 a[k++].num = A[i++].num; 38 } 39 while(j<=n) 40 { 41 a[k].grade = B[j].grade; 42 a[k++].num = B[j++].num; 43 } 44 } 45 int main() 46 { 47 cin>>n>>r>>q; 48 for(int i=1;i<=2*n;i++) 49 { 50 cin>>a[i].grade; 51 a[i].num=i; 52 } 53 for(int i=1;i<=2*n;i++) 54 cin>>w[i]; 55 sort(a+1,a+1+2*n,cmp); 56 for(int k=1;k<=r;k++) 57 { 58 int tt=1; 59 for(int i=1;i<2*n;i+=2) 60 { 61 if(w[a[i].num]>w[a[i+1].num]) 62 { 63 A[tt].grade = a[i].grade+1; 64 A[tt].num = a[i].num; 65 B[tt].grade = a[i+1].grade; 66 B[tt].num = a[i+1].num; 67 tt++; 68 } 69 else 70 { 71 A[tt].grade = a[i+1].grade+1; 72 A[tt].num = a[i+1].num; 73 B[tt].grade = a[i].grade; 74 B[tt].num = a[i].num; 75 tt++; 76 } 77 } 78 MergeSort(); 79 } 80 cout<<a[q].num<<endl; 81 return 0; 82 }