FZU ICPC 2020 寒假训练 5 —— 排序
P1177 【模板】快速排序
题目描述
利用快速排序算法将读入的 N 个数从小到大排序后输出。快速排序是信息学竞赛的必备算法之一。对于快速排序不是很了解的同学可以自行上网查询相关资料,掌握后独立完成。(C++ 选手请不要试图使用 STL,虽然你可以使用 sort 一遍过,但是你并没有掌握快速排序算法的精髓。)
输入格式
第 1 行为一个正整数 N,第 2 行包含 N 个空格隔开的正整数 ai,为你需要进行排序的数,数据保证了 Ai不超过 1e9。
输出格式
将给定的 N 个数从小到大输出,数之间空格隔开,行末换行且无空格。
输入 #1
5
4 2 4 5 1
输出 #1
1 2 4 4 5
Accepted
本题如果用sort函数是直接过的,但是为了更好的理解快排,我参考了题解的方法。同时看到了很多种的排序方式(今天做完题目就开始学习!)来源:洛谷
快速排序(quicksort)是20世纪60年代提出的一种算法,类似于归并,也有分治的一种思想,即找到一个基准数,将比它大的放在它的右边,比它小的放在它的左边。
1.基准数位置。
基准数的位置在教科书中一般选为最左边或最右边,我一般习惯于选最左边。不同选择对执行没有较大的影响。
2.左右移动的方式
目前我所见到的移动的方式,主要有两种,
一是j(从右)找到一个比基准数(记作k)小的数,然后让i(从左)找到一个比k大的数,然后进行交换。直到i,j相遇开始分治处理;
另一种是 基准数记作k,基准数下标记作x
① i(从左)找到一个比k大的数,a[x]=a[i];
② j(从右)找到一个比k小的数,a[i]=a[j];
③ i(从左)找到一个比k大的数,a[j]=a[i];
④ 重复②③直到i==j;
⑤ 将a[i]赋值为基准数k;
第一种是快排的原始思想,交换->分治,但是借用了t来交换a[i]和a[j];
第二种的思想巧妙一些,没有用一次三句话操作,而是每次交换,都可以保证a[i]>a[j]。
#include <stdio.h>
#include <math.h>
#include <string.h>
int a[1000000];
void sort(int left,int right){
int mid=a[(left+right)/2];//中间数
int i=left,j=right;
while(i<=j){
while(a[i]<mid) i++;//查找左半部分比中间数大的数
while (a[j]>mid) j--;//查找右半部分比中间数小的数
if(i<=j){//如果有一组不满足排序条件(左小右大)的数
int temp;
temp=a[i];
a[i]=a[j];
a[j]=temp;
i++;
j--;
}
}
if(left<j) sort(left,j);
if(right>i) sort(i, right);
}
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(0,n-1);
for(int i=0;i<n;i++){
printf("%d",a[i]);
if(i!=n-1) printf(" ");
}
return 0;
}
P1068 分数线划定
题目描述
世博会志愿者的选拔工作正在 A 市如火如荼的进行。为了选拔最合适的人才,A市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的150%划定,即如果计划录取m名志愿者,则面试分数线为排名第m×150%(向下取整)名的选手的分数,而最终进入面试的选手为笔试成绩不低于面试分数线的所有选手。
现在就请你编写程序划定面试分数线,并输出所有进入面试的选手的报名号和笔试成绩。
输入格式
第一行,两个整数 n,m(5≤n≤5000,3≤m≤n),中间用一个空格隔开,其中n表示报名参加笔试的选手总数,m表示计划录取的志愿者人数。输入数据保证 m×150%向下取整后小于等于 n。
第二行到第 n+1 行,每行包括两个整数,中间用一个空格隔开,分别是选手的报名号 k(1000≤k≤9999)和该选手的笔试成绩s(1≤s≤100)。数据保证选手的报名号各不相同。
输出格式
第一行,有2个整数,用一个空格隔开,第一个整数表示面试分数线;第二个整数为进入面试的选手的实际人数。
从第二行开始,每行包含2个整数,中间用一个空格隔开,分别表示进入面试的选手的报名号和笔试成绩,按照笔试成绩从高到低输出,如果成绩相同,则按报名号由小到大的顺序输出。
输入 #1
6 3
1000 90
3239 88
2390 95
7231 84
1005 95
1001 88
输出 #1
88 5
1005 95
2390 95
1000 90
1001 88
3239 88
说明/提示
【样例说明】
m×150%=3×150%=4.5,向下取整后为4。保证4个人进入面试的分数线为88,但因为88有重分,所以所有成绩大于等于
88 的选手都可以进入面试,故最终有5个人进入面试。
Accepted
这题一开始我还是使用快排,但是后面发现我无法就当分数相等时,对编号进行排序,就采用了sort函数+结构体的方法.
#include <stdio.h>
#include <math.h>
#include <string.h>
#include<algorithm>
struct player{
int s;
int k;
}a[100000];
bool cmp(player a1,player b1){ //注意这一步
if(a1.s==b1.s) return a1.k<b1.k;
return a1.s>b1.s;
}
int main(){
int n,i;
int m;
int num=0;
int score_num=0;
int score=0;
scanf("%d %d",&n,&m);
score_num=(int)m*1.5;
for(i=1;i<=n;i++)
scanf("%d %d",&a[i].k,&a[i].s);
std::sort(a+1,a+n+1,cmp);
score=a[score_num].s;
for(i=1;i<=n;i++){
if(a[i].s<score) a[i].s=0;
}
for(i=1;i<=n;i++){
if(a[i].s) num++;
}
printf("%d %d\n",score,num);
for(i=1;i<=n;i++){
if(a[i].s) printf("%d %d\n",a[i].k,a[i].s);
}
return 0;
}
P1781 宇宙总统
题目描述
地球历公元 6036 年,全宇宙准备竞选一个最贤能的人当总统,共有 n 个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统。
输入格式
第一行为一个整数 n,代表竞选总统的人数。接下来有 n 行,分别为第一个候选人到第 n 个候选人的票数。
输出格式
共两行,第一行是一个整数 m,为当上总统的人的号数。第二行是当上总统的人的选票。
输入 #1
5
98765
12365
87954
1022356
985678
输出 #1
4
1022356
说明/提示
票数可能会很大,可能会到100 位数字。
Accepted
这题看到提示就明白要对字符串进行比较,也是这一题让我看到了c++在对字符串进行操作时比c更加便利的地方:
#include <iostream>
#include <cstring>
#include<algorithm>
using namespace std;
int main(){
int n,i;
int num = 0;
string str_max="";
string str;
cin >> n;
for(i=1;i<=n;i++){
cin >> str;
int str_size=(int)str.size();
int str_max_size=(int)str_max.size();
if(str_size>str_max_size||(str_size>=str_max_size&&str>str_max)){
str_max=str;
num=i;
}
}
cout << num << endl << str_max << endl;
return 0;
}
当然这一题也可以用结构体+sort函数解决会比用c然后一位位比快的多(来源:洛谷):
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
string x; //装票数
int num; //装号数
int lenx; //装票数的位数
}s[25];
bool cmp(node a,node b)
{
if(a.lenx>b.lenx) return 1; //前一个比后一个位数多,不交换
if(a.lenx==b.lenx&&a.x>b.x) return 1; //位数相同,但前一个按字典序排列比后一个大,也不交换。
return 0; //剩下情况均要交换。
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i].x;
s[i].num=i; //存号数
s[i].lenx=s[i].x.size(); //存票数的位数
}
sort(s+1,s+n+1,cmp); //排序
cout<<s[1].num<<endl; //输出首位答案即可,注意先输出号数
cout<<s[1].x<<endl; //再输出票数
return 0;
}
P1309 瑞士轮
题目背景
在双人对决的竞技性比赛,如乒乓球、羽毛球、国际象棋中,最常见的赛制是淘汰赛和循环赛。前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高。后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长。
本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名。它可以看作是淘汰赛与循环赛的折中,既保证了比赛的稳定性,又能使赛程不至于过长。
题目描述
2×N 名编号为 1∼2N 的选手共进行R 轮比赛。每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名。选手的总分为第一轮开始前的初始分数加上已参加过的所有比赛的得分和。总分相同的,约定编号较小的选手排名靠前。
每轮比赛的对阵安排与该轮比赛开始前的排名有关:第 1 名和第 2 名、第 3 名和第 4名、……、第2K−1名和第2K名、…… 、第2N−1名和第2N名,各进行一场比赛。每场比赛胜者得1分,负者得 0分。也就是说除了首轮以外,其它轮比赛的安排均不能事先确定,而是要取决于选手在之前比赛中的表现。
现给定每个选手的初始分数及其实力值,试计算在R 轮比赛过后,排名第Q 的选手编号是多少。我们假设选手的实力值两两不同,且每场比赛中实力值较高的总能获胜。
输入格式
第一行是三个正整数N,R,Q,每两个数之间用一个空格隔开,表示有 2×N名选手、R 轮比赛,以及我们关心的名次 Q。
第二行是2×N 个非负整数s1,s2,…,s2N,每两个数之间用一个空格隔开,其中si表示编号为i 的选手的初始分数。 第三行是2×N 个正整数w1,w2,…,w2N,每两个数之间用一个空格隔开,其中 wi表示编号为i 的选手的实力值。
输出格式
一个整数,即R 轮比赛结束后,排名第Q 的选手的编号。
输入 #1
2 4 2
7 6 6 7
10 5 20 15
输出 #1
1
Wrong Answer
#include<algorithm>
#include <stdio.h>
struct player{
int s;
int w;
int num;
}a[1000000];
bool cmp(player a, player b){
if(a.s==b.s) return a.num<b.num;
return a.s>b.s;
}
int main(){
int n,i,q,r;
scanf("%d %d %d",&n,&r,&q);
for(i=1;i<=2*n;i++){
scanf("%d",&a[i].s);
a[i].num=i;
}
for(i=1;i<=2*n;i++){
scanf("%d",&a[i].w);
}
while(r--){
std::sort(a+1,a+1+2*n,cmp);
for(i=1;i<2*n;i+=2){
if(a[i].w>a[i+1].w) a[i].s++;
else a[i+1].s++;
}
}
std::sort(a+1,a+1+2*n,cmp);
printf("%d\n",a[q].num);
return 0;
}
Accepted
这题我刚刚开始采用快排,但是仍有两个点没过去,开了O2才AC,后面看了题解才知道,这一题需要用到的是归并排序的方法:(来源:洛谷)
一、关于sort的浪费
首先让我们想想,sort其实就是快速排序。稳定的话O(nlogn)左右。但是仔细想想此题——每次需要更新的值,都是相邻两个人变化后的分数;而相邻的分数,有些是不会改变位置的,而快速排序则是每次全部修改,必然会造成浪费。
二、关于归并排序
然后考虑归并排序: 归并排序的思想就是合并两个同序数组的线性方式——每次比较两个有序数组指针指向的值,谁更小(大)则放到temp数组里,然后删掉进入temp的元素,指针++。
#include<algorithm>
#include <stdio.h>
struct player{
int s;
int num;
}a[2000005];
player v[200005],l[200005];//v:胜者组 l:败者组
bool cmp(player a, player b){
if(a.s==b.s) return a.num<b.num;
return a.s>b.s;
}
//将胜者组v和败者组l合并到stu中
void merge(int n){
int i=1,j=1,k=1;
while(i<=n&&j<=n){
if(v[i].s>l[j].s||(v[i].s==l[j].s&&v[i].num<l[j].num)){
a[k].s=v[i].s;
a[k].num=v[i].num;
k++;
i++;
}
else{
a[k].s=l[j].s;
a[k].num=l[j].num;
k++;
j++;
}
}
while(i<=n){
a[k].s=v[i].s;
a[k].num=v[i].num;
k++;
i++;
}
while(j<=n){
a[k].s=l[j].s;
a[k].num=l[j].num;
k++;
j++;
}
}
int main(){
int n,i,q,r;
int w[2000005];
scanf("%d %d %d",&n,&r,&q);
for(i=1;i<=2*n;i++){
scanf("%d",&a[i].s);
a[i].num=i;
}
for(i=1;i<=2*n;i++){
scanf("%d",&w[i]);
}
std::sort(a+1,a+1+2*n,cmp);//【快排】(未开始比赛前,所有选手都是无序的)
for(int t=1;t<=r;t++){
int ind=1;//// 胜者组a和败者组b的下标
for(i=1;i<2*n;i+=2){
if(w[a[i].num]>w[a[i+1].num]){
v[ind].s=a[i].s+1;
v[ind].num=a[i].num;
l[ind].s=a[i+1].s;
l[ind].num=a[i+1].num;
ind++;
}
else{
v[ind].s=a[i+1].s+1;
v[ind].num=a[i+1].num;
l[ind].s=a[i].s;
l[ind].num=a[i].num;
ind++;
}
}
merge(n);
}
printf("%d\n",a[q].num);
return 0;
}
FZU ICPC 2020 寒假训练 5 —— 排序的更多相关文章
- FZU ICPC 2020 寒假训练 4 —— 模拟(一)
P1042 乒乓球 题目背景 国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及.其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役.华华 ...
- FZU ICPC 2020 寒假训练 2
A - 排序 输入一行数字,如果我们把这行数字中的'5'都看成空格,那么就得到一行用空格分割的若 干非负整数(可能有些整数以'0'开头,这些头部的'0'应该被忽略掉,除非这个整数就是由 若干个'0'组 ...
- FZU ICPC 2020 寒假训练 6 —— 字符串处理
P1603 斯诺登的密码 题目描述 2013年X月X日,俄罗斯办理了斯诺登的护照,于是他混迹于一架开往委内瑞拉的飞机.但是,这件事情太不周密了,因为FBI的间谍早已获悉他的具体位置--但这不是最重要的 ...
- FZU ICPC 2020 寒假训练 4 —— 模拟(二)
P1056 排座椅 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的 D 对同 ...
- FZU ICPC 2020 寒假训练 3
P1308 统计单词数 题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数.现在,请你编程实现这一功能,具体要求是:给定一 ...
- FZU ICPC 2020 寒假训练 1
B - Sum Problem In this problem, your task is to calculate SUM(n) = 1 + 2 + 3 + ... + n. Input The i ...
- FZU ICPC 2020 寒假阶段测试 2
P1464 Function 题目描述 对于一个递归函数w(a,b,c)如果a≤0 or b≤0 or c≤0就返回值1.如果a>20 or b>20 or c>20就返回w(20, ...
- LeetCode编程训练 - 拓扑排序(Topological Sort)
拓扑排序基础 拓扑排序用于解决有向无环图(DAG,Directed Acyclic Graph)按依赖关系排线性序列问题,直白地说解决这样的问题:有一组数据,其中一些数据依赖其他,问能否按依赖关系排序 ...
- [蓝桥杯]ALGO-97.算法训练_排序
题目描述: 问题描述 编写一个程序,输入3个整数,然后程序将对这三个整数按照从大到小进行排列. 输入格式:输入只有一行,即三个整数,中间用空格隔开. 输出格式:输出只有一行,即排序后的结果. 输入输出 ...
随机推荐
- 深入浅出WPF-11.Template(模板)02
模板 DataTemplate和ControlTemplate的关系 通过上面的内容,控件只是一个数据和行为的载体,是一个抽象的概念,至于它长什么样子,或者它的数据是怎么展示的,都是由模板生成的.决定 ...
- 如何从阿里云Code升级至云效Codeup
如果你还在使用阿里云Code,不防看看如何从阿里云Code升级至云效Codeup,云效代码管理Codeup是阿里云出品的一款企业级代码管理平台,提供代码托管.代码评审.代码扫描.质量检测等功能,全方位 ...
- Dapr + .NET Core实战(八)服务监测
服务监测 分布式服务性能指标,链路追踪,运行状况,日志记录都很重要,我们日常开发中为了实现这些功能需要集成很多功能,替换监控组件时成本也很高. Dapr 可观测性模块将服务监测与应用程序分离.它自动捕 ...
- 好未来数据中台 Node.js BFF实践(一):基础篇
好未来数据中台 Node.js BFF实践系列文章列表: 基础篇 实战篇(TODO) 进阶篇(TODO) 好未来数据中台的Node.js中间层从7月份开始讨论可行性,截止到9月已经支持了4个平台,其中 ...
- CSS 奇技淫巧 | 妙用 drop-shadow 实现线条光影效果
本文将介绍一种利用 CSS 滤镜 filter 的 drop-shadow(),实现对 HTML 元素及 SVG 元素的部分添加阴影效果,以实现一种酷炫的光影效果,用于各种不同的场景之中.通过本文,你 ...
- node ***.js或npm run scripts的脚本命令出现Cannot find module 'react-dev-utils/getPublicUrlOrPath'报错的解决办法
出现类似Cannot find module 'react-dev-utils/getPublicUrlOrPath'一般是项目中没有下载报错中提到的模块(可以在项目中package.json文件de ...
- Python基础 | 字符串格式化输出及print()函数介绍
在写代码时,我们会经常与字符串打交道,Python中控制字符串格式通常有三种形式,分别是使用str%,str.format(),f-str,用法都差不多,但又有一些细微之差. 一起来看看吧~~~ 一. ...
- Git学习笔记01-安装
首先,什么是git? git是开源的分布式系统,能够将团队的项目上传至git,供团队修改demo 第一步:安装好git(推荐淘宝镜像下载,地址https://npm.taobao.org/mirror ...
- 2020.10.9--vj个人赛补题
B - A Tide of Riverscape 题意:给出一组字符串,由'0','1',' . '组成,' . '可以换成 0或1,判断第 i 个和第 i+p 个字符是否可以不相等,如果可以则输出 ...
- FastAPI 学习之路(四十二)定制返回Response
我们想要在接口中返回xml格式的内容,我们应该如何实现呢. from fastapi import FastAPI,Response @app.get("/legacy/") de ...