当前位置:   article > 正文

三道排序题

三道排序题

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)的排序算法,这里我用的是快速排序。

源代码

  1. #include<stdio.h>
  2. int a[100010];
  3. void swap(int *a,int *b)//交换两个数的位置
  4. {
  5. int t=*a;
  6. *a=*b;
  7. *b=t;
  8. }
  9. //快速排序
  10. void q(int l,int r)
  11. {
  12. if(l>=r)
  13. return;
  14. int mid=l-1;
  15. int tr=r+1;
  16. int tl=l-1;
  17. int v=a[(l+r)/2];
  18. int i=1;
  19. while(mid<tr-1)
  20. {
  21. if(a[mid+1]<v)
  22. {
  23. if(mid==tl)
  24. {
  25. mid++;
  26. tl++;
  27. }
  28. else
  29. {
  30. swap(&a[++tl],&a[++mid]);
  31. }
  32. }
  33. else if(a[mid+1]==v)
  34. {
  35. mid++;
  36. }
  37. else
  38. {
  39. swap(&a[mid+1],&a[--tr]);
  40. }
  41. }
  42. q(l,tl);
  43. q(tr,r);
  44. }
  45. int main()
  46. {
  47. int n;
  48. scanf("%d",&n);
  49. for(int i=0;i<n;i++)
  50. {
  51. scanf("%d",&a[i]);
  52. }
  53. q(0,n-1);
  54. for(int i=0;i<n-1;i++)
  55. {
  56. printf("%d ",a[i]);
  57. }
  58. printf("%d\n",a[n-1]);
  59. return 0;
  60. }

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 个人进入面试。

解题过程 

因为当成绩相同时需要按报名号由小到大的顺序输出,所以在对成绩进行从大到小的排序时,还需要对成绩相同的选手的报名号进行从小到大的排序。

源代码

  1. #include<stdio.h>
  2. typedef struct{
  3. int num;
  4. int grade;
  5. }P;
  6. P p[5010];
  7. void swap(P *a,P *b)
  8. {
  9. P t=*a;
  10. *a=*b;
  11. *b=t;
  12. }
  13. //根据成绩相同选手的报名号进行从小到大排序
  14. void q1(int l,int r)
  15. {
  16. if(l>=r)
  17. return;
  18. int mid=l-1;
  19. int tr=r+1;
  20. int tl=l-1;
  21. int v=p[(l+r)/2].num;
  22. int i=1;
  23. while(mid<tr-1)
  24. {
  25. if(p[mid+1].num<v)
  26. {
  27. if(mid==tl)
  28. {
  29. mid++;
  30. tl++;
  31. }
  32. else
  33. {
  34. swap(&p[++tl],&p[++mid]);
  35. }
  36. }
  37. else if(p[mid+1].num==v)
  38. {
  39. mid++;
  40. }
  41. else
  42. {
  43. swap(&p[mid+1],&p[--tr]);
  44. }
  45. }
  46. q1(l,tl);
  47. q1(tr,r);
  48. }
  49. void q(int l,int r)
  50. {
  51. if(l>=r)
  52. return;
  53. int mid=l-1;
  54. int tr=r+1;
  55. int tl=l-1;
  56. int v=p[(l+r)/2].grade;
  57. int i=1;
  58. while(mid<tr-1)
  59. {
  60. if(p[mid+1].grade>v)
  61. {
  62. if(mid==tl)
  63. {
  64. mid++;
  65. tl++;
  66. }
  67. else
  68. {
  69. swap(&p[++tl],&p[++mid]);
  70. }
  71. }
  72. else if(p[mid+1].grade==v)
  73. {
  74. mid++;
  75. }
  76. else
  77. {
  78. swap(&p[mid+1],&p[--tr]);
  79. }
  80. }
  81. q(l,tl);
  82. q(tr,r);
  83. //根据成绩相同选手的报名号进行从小到大排序
  84. q1(tl+1,tr-1);
  85. }
  86. int main()
  87. {
  88. int m,n;
  89. scanf("%d%d",&n,&m);
  90. for(int i=1;i<=n;i++)
  91. {
  92. scanf("%d%d",&p[i].num,&p[i].grade);
  93. }
  94. q(1,n);
  95. //计算分数线
  96. int k=m*3/2;
  97. int k1=p[k].grade;
  98. //计算通过人数
  99. int k2;
  100. for(k2=k+1;p[k2].grade==k1;k2++);
  101. printf("%d %d\n",k1,k2-1);
  102. for(int i=1;i<=k2-1;i++)
  103. {
  104. printf("%d %d\n",p[i].num,p[i].grade);
  105. }
  106. return 0;
  107. }

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 普及组 第一题

解题过程 

这题可以先对随机数进行快排,然后遍历排序后的随机数统计出不同随机数的个数,但由于输出所有不同随机数时也需要一个循环遍历,所以我们考虑在快排的过程中统计重复随机数的个数。

源代码

  1. #include<stdio.h>
  2. int a[10010];
  3. int b[1010];
  4. int ans;//用来统计重复随机数的个数
  5. void swap(int *a,int *b)
  6. {
  7. int t=*a;
  8. *a=*b;
  9. *b=t;
  10. }
  11. void q(int l,int r)
  12. {
  13. if(l>=r)
  14. return;
  15. int mid=l-1;
  16. int tr=r+1;
  17. int tl=l-1;
  18. int v=a[(l+r)/2];
  19. int i=1;
  20. while(mid<tr-1)
  21. {
  22. if(a[mid+1]<v)
  23. {
  24. if(mid==tl)
  25. {
  26. mid++;
  27. tl++;
  28. }
  29. else
  30. {
  31. swap(&a[++tl],&a[++mid]);
  32. }
  33. }
  34. else if(a[mid+1]==v)
  35. {
  36. mid++;
  37. }
  38. else
  39. {
  40. swap(&a[mid+1],&a[--tr]);
  41. }
  42. }
  43. if(tr-tl>2)//有重复随机数出现时tr-tl>2
  44. ans+=tr-tl-2;
  45. q(l,tl);
  46. q(tr,r);
  47. }
  48. int main()
  49. {
  50. int n;
  51. scanf("%d",&n);
  52. for(int i=0;i<n;i++)
  53. {
  54. scanf("%d",&a[i]);
  55. }
  56. q(0,n-1);
  57. ans=n-ans;//得出不同随机数的个数
  58. printf("%d\n",ans);
  59. for(int i=0;i<n;i++)
  60. {
  61. if(!b[a[i]])
  62. {
  63. printf("%d ",a[i]);
  64. b[a[i]]=1;
  65. }
  66. }
  67. return 0;
  68. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/465234
推荐阅读
相关标签
  

闽ICP备14008679号