排序练习
大统领投票
题目描述
第一届地球大统领开始选拔,全地球的所有生物都积极参与投票,现在已知得票结果,请输出新当选的得票数最多的地球大统领的编号和得票数。
输入
输入第一行为一个整数 NN 表示参选生物数。(1≤N≤100)(1≤N≤100)
接下来 NN 行,每行一个整数,表示第 ii 名参选生物的票数。票数不会超过 10001000位。
输出
输出得票数最多的生物的编号和票数。
样例输入
3
123456799
123456789132456789123456789
11111111111111
样例输出
2
123456789132456789123456789
#include <iostream>
#include<string>
#include<algorithm>
using namespace std;
//符串读入可以直接比较大小
struct node{
int num;
string s;
};
int n;
node p[105];//本质是个类,这里是结构体数组
bool cmp(node a,node b){//sort就是从小到大排序,自定义可以加入cmp,返回类型为bool。
if(a.s.size()==b.s.size()){
return a.s>b.s;
}
return a.s.size()>b.s.size()
}
int main() {
cin>>n;
for(int i=1;i<=n;i++){
cin>>p[i].s;
p[i].num=i;
}
sort(p+1,p+n+1,cmp);
cout<<p[1].num<<endl<<p[1].s<<endl;
return 0;
}
二谁拿了最多讲学金
题目描述
某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同:
1.院士奖学金,每人 80008000 元,期末平均成绩高于 8080 分(>80>80),并且在本学期内发表 11 篇或 11 篇以上论文的学生均可获得;
2.五四奖学金,每人 40004000 元,期末平均成绩高于 8585 分(>85>85),并且班级评议成绩高于 8080 分(>80>80)的学生均可获得;
3.成绩优秀奖,每人 20002000 元,期末平均成绩高于 9090 分(>90>90)的学生均可获得;
4.西部奖学金,每人 10001000 元,期末平均成绩高于 8585 分(>85>85)的西部省份学生均可获得;
5.班级贡献奖,每人 850850 元,班级评议成绩高于 8080 分(>80>80)的学生干部均可获得;
只要符合条件就可以得奖,每项奖学金的获奖人数没有限制,每名学生也可以同时获得多项奖学金。例如姚林的期末平均成绩是 8787 分,班级评议成绩 8282 分,同时他还是一位学生干部,那么他可以同时获得五四奖学金和班级贡献奖,奖金总数是 48504850元。
现在给出若干学生的相关数据,请计算哪些同学获得的奖金总数最高(假设总有同学能满足获得奖学金的条件)。
输入
第一行是 11 个整数 N(1≤N≤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
#include <iostream>
#include<string>
#include<algorithm>
using namespace std;
struct person{
string name;
int avg,cla,paper,m,num;
char off,west;
};
int n,ans;
person stu[105];
bool cmp(person a,person b){
if(a.m==b.m){
return a.m>b.m;
}
return a.m>b.m;
}
int func(int i){
int t=0;
if(stu[i].avg>80&&stu[i].paper>=1)t+=8000;
if(stu[i].avg>85&&stu[i].cla>80)t+=4000;
if(stu[i].avg>90)t+=2000;
if(stu[i].avg>85&&stu[i].west=='Y')t+=1000;
if(stu[i].cla>80&&stu[i].off=='Y')t+=850
return t;
}
int main() {
cin>>n;
for(int i=0;i<n;i++){
cin>>stu[i].name>>stu[i].avg>>stu[i].cla<<stu[i].off<<stu[i].paper;
stu[i].num=i;
stu[i].m=func(i);
ans+=stu[i].m;
}
sort(stu,stu+n,cmp);
cout<<stu[0].name<<endl<<stu[0].m<<endl<<ans<<endl;
return 0;
}
二分法
吃瓜群众
题目描述
某地总共有 MM 堆瓜,第 ii 堆瓜的数量为 XiXi。现有 NN 组群众现在想要吃瓜,第 ii 组群众想要吃的瓜的数量为 YiYi。现在对于每组想吃瓜的群众,需要在 MM 堆瓜中查找对应数量的一堆瓜,并输出那堆瓜的编号,若找不到对应数量的一堆,则输出 00。
输入
输入共 33 行。
第一行两个整数 M,NM,N。
第二行 MM 个整数分别表示 X1,X2…XMX1,X2…XM。(保证各不相同)
第三行 NN 个整数分别表示 Y1,Y2…YNY1,Y2…YN。(保证各不相同)
输出
对于每个 YiYi 输出一行一个整数为对应数量的瓜的编号,若没有对应数量的瓜,则输出 00。
样例输入
5 3
1 3 26 7 15
26 99 3
样例输出
3
0
2
#include <iostream>
#include<algorithm>
using namespace std;
struct node{
int cnt,num;
};
int n,ans;
node wm[100005];
bool cmp(const node &a,const node &b){
return a.num<b.num;
}
int main() {
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>wm[i].num;
wm[i].cnt=i+1;
}
sort(wm,wm+n,cmp);
for(int i=0;i<m;i++){
int t,f=0,l=0,r=n-1;
cin>>t;
while(l<=r){
int mid=(l+r)/2;
if(t==wm[mid].num){
f=wm[mid].cnt;
break;
}
if(t<wm[mid].num){
r=mid-1;
}else{
l=mid+1
}
}
cout<<f<<endl;
}
return 0;
}
吃瓜升级
题目描述
某地总共有 MM 堆瓜,第 ii 堆瓜的数量为 XiXi。现有 NN 组群众现在想要吃瓜,第 ii 组群众想要吃的瓜的数量为 YiYi。现在对于每组想吃瓜的群众,需要在 MM 堆瓜中查找大于等于需要数量的第一堆瓜,并输出那堆瓜的编号,若所有瓜堆的数量均小于需要数量,则输出 00。
输入
输入共 33 行。
第一行两个整数 M,NM,N。
第二行 MM 个整数分别表示 X1,X2…XMX1,X2…XM。(保证各不相同)
第三行 NN 个整数分别表示 Y1,Y2…YNY1,Y2…YN。(保证各不相同)
输出
对于每个 YiYi 输出一行一个整数为大于等于需要数量的第一堆瓜的编号,若所有瓜堆的数量均小于需要数量,则输出 00。
样例输入
5 5
1 3 26 7 15
27 10 3 4 2
样例输出
0
5
2
4
2
#include <iostream>
#include<string>
#include<algorithm>
using namespace std;
//这题是上一题的升级,本题要注意mid是否在区间 。可以把数组按照是否符合要求改为01的数组
struct node{
int cnt,num;
};
int n,m;
node wm[100005];
bool cmp(const node &a,const node &b){
return a.num<b.num;
}
int main() {m
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>wm[i].num;
wm[i].cnt=i+1;
}
wm[n].cnt=0;
wm[n].num=2100000000;
sort(wm,wm+n+1,cmp);
for(int i=0;i<m;i++){
int t,l=0,r=n-1;
cin>>t;
while(l!=r){ //左右两边都来
int mid=(l+r)/2;
if(t<=wm[mid].num){
r=mid;
}else{
l=mid+1
}
}
cout<<wm[l].cnt<<endl;
}
return 0;
}
后面再慢慢更新吧,打算把自己的学习路线啥的也整理一下不然感觉学的老是忘啊。
更新线的拉,慢慢整不着急。最近有点小忙。下次看看能不能搞定思维导图啥的,毕竟算法题还是有点是外带的感觉。
原木切割
题目描述
某林业局现在 NN 根原木,长度分别为 XiXi,为了便于运输,需要将他们切割成长度相等的 MM 根小段原木(只能切割成整数长度,可以有剩余),小段原木的长度越大越好,现求小段原木的最大长度。例如,有 33 根原木长度分别为 6,15,226,15,22,现在需要切成 88 段,那么最大长度为 55。
输入
第一行两个整数 N,MN,M。(1≤N≤100,000,1≤M≤100,000,000)(1≤N≤100,000,1≤M≤100,000,000)
接下来 NN 行,每行一个数,表示原木的长度 XiXi。(1≤Xi≤100,000,0001≤Xi≤100,000,000)
输出
输出小段原木的最大长度, 保证可以切出 MM 段。
样例输入
3 8
6
15
22
样例输出
5
#include<iostream>
using namespace std;
//二分答案,需要按照题目具体考虑
int n,m,num[100005],lr;
int func(int len){
int s=0;
for(int i=0;i<n;i++){
s+=num[i]/len;
}
return s;
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>num[i];
lr=max(lr,num[i]);
}
int l=1,r=lr;
while(l!=r){
int mid=(l+r+1)/2;
int s=func(mid);
if(s>=m){
l=mid;
}else{
r=mid-1;
}
}
cout<<l<<endl;
return 0;
}
切绳子
题目描述
有 NN 条绳子,它们的长度分别为 LiLi。如果从它们中切割出 KK 条长度相同的绳子,这 KK 条绳子每条最长能有多长?答案保留到小数点后 22 位(直接舍掉 22 位后的小数)。
输入
第一行两个整数 NN 和 KK,接下来 NN 行,描述了每条绳子的长度 LiLi。
输出
切割后每条绳子的最大长度,保证答案大于零。
样例输入
4 11
8.02
7.43
4.57
5.39
样例输出
2.00
#include<iostream>
#include<cstdio>
using namespace std;
int n,m;
double num[10005],tr;
int func(double len){
int s=0;
for(int i=0;i<n;i++){
s+=num[i]/len;
}
return s;
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>num[i];
tr=max(tr,num[i]);
}
double l=0,r=tr;
while(r-l>0.00001){ //和精度相关,比较友好的一道题
double mid =(l+r)/2;
int s=func(mid);
if(s>=m){
l=mid;
}else{
r=mid;
}
}
//直接用会四舍五入了改用点数学的
printf("%.2f\n",(int)(l*100)/100.0);
return 0;
}
分座位
题目描述
某公司的程序猿每天都很暴躁,因为他们每个人都认为其他程序猿和自己风格不同,无法一同工作,当他们的工位的编号距离太近时,他们可能会发生语言甚至肢体冲突,为了尽量避免这种情况发生,现在公司打算重新安排工位,因为有些关系户的工位是固定的,现在只有一部分工位空了出来,现在有 NN 个程序猿需要分配在 MM 个工位中,第 ii 个工位的编号为 XiXi,工位编号各不相同,现在要求距离最近的两个程序猿之间的距离最大,求这个最大距离是多少。XiXi 和 XjXj 工位之间距离为|Xi−Xj||Xi−Xj|。
输入
输入共 M+1M+1 行。
第一行两个整数 M,NM,N。(1≤N≤M≤100,000)(1≤N≤M≤100,000)
接下来 MM 行,每行一个数,表示剩余的工位的编号。
输出
输出距离最近的两个程序猿之间的最大距离。
样例输入
5 3
1
2
8
4
9
样例输出
3
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,num[100005],tr;
int func(int d){
int s=1,last=num[0];
for(int i=1;i<n;i++){
if(num[i]-last>=d){
s++;
last=num[i];
}
}
return s;
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>num[i];
tr=max(tr,num[i]);
}
sort(num,num+n);//小到大
int l=1,r=tr;
while(l!=r){
int mid =(l+r+1)/2;
int s=func(mid);
if(s>=m){
l=mid;
}else{
r=mid-1;
}
}
cout<<l<<endl;
return 0;
}
总结
这几道题都差不了太多,二分查找大概也都差不多。1.普通的二分查找,就课本上那种。
2.二分查找的特殊情况就是按照题目分000011111或者可以111110000的特殊情况。
//000011111
while(l!=r){
mid=(l+r)/2;
l=mid+1;
r=mid;
}
//111110000
while(l!=r){
mid=(l+r+1)/2;
l=mid;
r=mid-1;
}
3.二分答案:就是先给出了二分的答案,一般是和那两种特殊情况差不多,不过会按照题目的不同来找不同的1的位置