P1177 【模板】排序
题目描述
原题点这里-->P1177 【模板】排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
将读入的 �N 个数从小到大排序后输出。
输入格式
第一行为一个正整数 N。
第二行包含 N 个空格隔开的正整数 ai,为你需要进行排序的数。
输出格式
将给定的 N 个数从小到大输出,数之间空格隔开,行末换行且无空格。
输入输出样例
输入 #1
5
4 2 4 5 1
输出 #1
1 2 4 4 5
说明/提示
对于 20%20% 的数据,有 1≤N≤1000;
对于 100%100% 的数据,有 1≤N≤100000,1≤ai≤1000000000。
解题过程
这道题需要时间复杂度为O(nlogn)的排序算法,这里我用的是快速排序。
源代码
cpp
#include<stdio.h>
int a[100010];
void swap(int *a,int *b)//交换两个数的位置
{
int t=*a;
*a=*b;
*b=t;
}
//快速排序
void q(int l,int r)
{
if(l>=r)
return;
int mid=l-1;
int tr=r+1;
int tl=l-1;
int v=a[(l+r)/2];
int i=1;
while(mid<tr-1)
{
if(a[mid+1]<v)
{
if(mid==tl)
{
mid++;
tl++;
}
else
{
swap(&a[++tl],&a[++mid]);
}
}
else if(a[mid+1]==v)
{
mid++;
}
else
{
swap(&a[mid+1],&a[--tr]);
}
}
q(l,tl);
q(tr,r);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
q(0,n-1);
for(int i=0;i<n-1;i++)
{
printf("%d ",a[i]);
}
printf("%d\n",a[n-1]);
return 0;
}
P1068 [NOIP2009 普及组] 分数线划定
题目描述
原题点这里-->P1068 [NOIP2009 普及组] 分数线划定 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
世博会志愿者的选拔工作正在 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)。数据保证选手的报名号各不相同。
输出格式
第一行,有 22 个整数,用一个空格隔开,第一个整数表示面试分数线;第二个整数为进入面试的选手的实际人数。
从第二行开始,每行包含 22 个整数,中间用一个空格隔开,分别表示进入面试的选手的报名号和笔试成绩,按照笔试成绩从高到低输出,如果成绩相同,则按报名号由小到大的顺序输出。
输入输出样例
输入 #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,向下取整后为 44。保证 44 个人进入面试的分数线为 8888,但因为 8888 有重分,所以所有成绩大于等于 8888 的选手都可以进入面试,故最终有 55 个人进入面试。
解题过程
因为当成绩相同时需要按报名号由小到大的顺序输出,所以在对成绩进行从大到小的排序时,还需要对成绩相同的选手的报名号进行从小到大的排序。
源代码
cpp
#include<stdio.h>
typedef struct{
int num;
int grade;
}P;
P p[5010];
void swap(P *a,P *b)
{
P t=*a;
*a=*b;
*b=t;
}
//根据成绩相同选手的报名号进行从小到大排序
void q1(int l,int r)
{
if(l>=r)
return;
int mid=l-1;
int tr=r+1;
int tl=l-1;
int v=p[(l+r)/2].num;
int i=1;
while(mid<tr-1)
{
if(p[mid+1].num<v)
{
if(mid==tl)
{
mid++;
tl++;
}
else
{
swap(&p[++tl],&p[++mid]);
}
}
else if(p[mid+1].num==v)
{
mid++;
}
else
{
swap(&p[mid+1],&p[--tr]);
}
}
q1(l,tl);
q1(tr,r);
}
void q(int l,int r)
{
if(l>=r)
return;
int mid=l-1;
int tr=r+1;
int tl=l-1;
int v=p[(l+r)/2].grade;
int i=1;
while(mid<tr-1)
{
if(p[mid+1].grade>v)
{
if(mid==tl)
{
mid++;
tl++;
}
else
{
swap(&p[++tl],&p[++mid]);
}
}
else if(p[mid+1].grade==v)
{
mid++;
}
else
{
swap(&p[mid+1],&p[--tr]);
}
}
q(l,tl);
q(tr,r);
//根据成绩相同选手的报名号进行从小到大排序
q1(tl+1,tr-1);
}
int main()
{
int m,n;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&p[i].num,&p[i].grade);
}
q(1,n);
//计算分数线
int k=m*3/2;
int k1=p[k].grade;
//计算通过人数
int k2;
for(k2=k+1;p[k2].grade==k1;k2++);
printf("%d %d\n",k1,k2-1);
for(int i=1;i<=k2-1;i++)
{
printf("%d %d\n",p[i].num,p[i].grade);
}
return 0;
}
P1059 [NOIP2006 普及组] 明明的随机数
题目描述
原题点这里-->P1059 [NOIP2006 普及组] 明明的随机数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 11 到 1000 之间的随机整数 (N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成"去重"与"排序"的工作。
输入格式
输入有两行,第 1 行为 1 个正整数,表示所生成的随机数的个数 N。
第 2 行有 N 个用空格隔开的正整数,为所产生的随机数。
输出格式
输出也是两行,第 1 行为 1 个正整数 M,表示不相同的随机数的个数。
第 2 行为 M 个用空格隔开的正整数,为从小到大排好序的不相同的随机数。
输入输出样例
输入 #1
10
20 40 32 67 40 20 89 300 400 15
输出 #1
8
15 20 32 40 67 89 300 400
说明/提示
NOIP 2006 普及组 第一题
解题过程
这题可以先对随机数进行快排,然后遍历排序后的随机数统计出不同随机数的个数,但由于输出所有不同随机数时也需要一个循环遍历,所以我们考虑在快排的过程中统计重复随机数的个数。
源代码
cpp
#include<stdio.h>
int a[10010];
int b[1010];
int ans;//用来统计重复随机数的个数
void swap(int *a,int *b)
{
int t=*a;
*a=*b;
*b=t;
}
void q(int l,int r)
{
if(l>=r)
return;
int mid=l-1;
int tr=r+1;
int tl=l-1;
int v=a[(l+r)/2];
int i=1;
while(mid<tr-1)
{
if(a[mid+1]<v)
{
if(mid==tl)
{
mid++;
tl++;
}
else
{
swap(&a[++tl],&a[++mid]);
}
}
else if(a[mid+1]==v)
{
mid++;
}
else
{
swap(&a[mid+1],&a[--tr]);
}
}
if(tr-tl>2)//有重复随机数出现时tr-tl>2
ans+=tr-tl-2;
q(l,tl);
q(tr,r);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
q(0,n-1);
ans=n-ans;//得出不同随机数的个数
printf("%d\n",ans);
for(int i=0;i<n;i++)
{
if(!b[a[i]])
{
printf("%d ",a[i]);
b[a[i]]=1;
}
}
return 0;
}