这些都是排序类型的题,很多可以用sort直接就出来了,但是很多的东西需要自己敲出来,只有自己一点一点的敲出来,才能是自己的。
P1177 【模板】快速排序
链接:https://www.luogu.org/problemnew/show/P1177
题意:就是简单的排序但是有时间限制。
题解:一开始我就准备用最原始的快排,但是有三处样例TLE,所以想到了对快排进行有一定的优化。
原始:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int a[1000001];//这就是最原始的快排
void quicksort(int left, int right){
int i = left, j = right;
if(left > right)
return ;
int tmp = a[left];
while(i != j){
while(a[j] >= tmp && j > i)j--;
while(a[i] <= tmp && i < j )i++;
if(i < j){
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
a[left] = a[i];
a[i] = tmp;
quicksort(left, i - 1);
quicksort(i + 1,right);
}
int main(){
int n;
while(~scanf("%d", &n)){
int i;
for(i = 0; i < n; i++){
scanf("%d", &a[i]);
}
quicksort(0, n - 1);
for(i = 0; i < n; i++)printf("%d ", a[i]);
}
}
优化:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int a[100001];
void quicksort(int left, int right){
int i = left, j = right;
int mid = a[(right + left) / 2];//中间的数为基准
while(i <= j){
while(a[j] > mid)j--;//如果右边的数大于中间的j--
while(a[i] < mid )i++;//如果左边的数大于小于中间的i++
if(i <= j){//如果满足i <= j的情况,交换位置,i++,j--
int t = a[i];
a[i] = a[j];
a[j] = t;
i++;
j--;
}
}//此时while循环已经跳出,如果left < j;递归下去
if(left < j){
quicksort(left, j);
}//i < right,也递归下去
if(i < right){
quicksort(i,right);
}
return ;
}
int main(){
int n;
while(~scanf("%d", &n)){
int i;
for(i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
quicksort(1, n);
for(i = 1; i <= n; i++){
if(i != 1)printf(" ");
printf("%d", a[i]);
}
printf("\n");
}
}
补充
归并排序:
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int arr[100005], temp[100005];
void Merge(int left, int mid, int right){//合并
int i = left;
int j = mid + 1;
int t = 0;
while(i <= mid && j <= right){//两个数组开始比较
if(arr[i] <= arr[j])temp[t++] = arr[i++];
else temp[t++] = arr[j++];
}
while(i <= mid){//比较结束之后左边还有剩余
temp[t++] = arr[i++];
}
while(j <= right){//比较之后右边还有剩余
temp[t++] = arr[j++];
}
t = 0;
while(left <= right){//复制temp给arr
arr[left++] = temp[t++];
}
}
void Sort(int left, int right){
if(left < right){
int mid = (left + right) / 2;
Sort(left, mid);//划分
Sort(mid + 1, right);//划分
Merge(left, mid, right);//合并
}
}
int main(){
int n;
while(~scanf("%d", &n)){
int i;
for(i = 0; i < n; i++){
scanf("%d", &arr[i]);
}
Sort(0, n - 1);
for(i = 0; i < n; i++){
if(i != 0)printf(" ");
printf("%d", arr[i]);
}
printf("\n");
}
return 0;
}
P1059 明明的随机数
链接:https://www.luogu.org/problemnew/show/P1059
题意:给你一串数,让你筛重,输出剩下有多少个数,最后让你按照从小到大的顺序输出每一个数。
题解:因为数据不大,最多也就有100个,最大的数也就1000,所以这道可以用桶排的方法去筛查重复的和按照从小到大的顺序输出。除此之外,还可以用Stl里面的Set,Set是集合,不能有重复的,而且输出的时候按照从小到大的顺序输出。下面的代码就是用Set。
#include<iostream>
#include<cstdio>
#include<set>
using namespace std;
set<int>s;
set<int>::iterator it;//迭代器
int main(){
int n, t;
while(~scanf("%d",&n)){
int i;
for(i = 0; i < n; i++){
scanf("%d", &t);
s.insert(t);//插入
}
int cnt = 0;
printf("%d\n",s.size());//多少个不重复的元素
for(it = s.begin(); it != s.end(); it++){//遍历
cnt++;
if(cnt != 1)printf(" ");
printf("%d", *it);
}
printf("\n");
}
return 0;
}
P1068 分数线划定
链接:https://www.luogu.org/problemnew/show/P1068
题意:就是告诉你一组数据,每一行包括两个数据,成绩按照从大到到的顺序,如果成绩一样,按照序号从小到大的顺序。
题解:看到这道题,很容易想到Sort函数的重载。但是这道题有些小细节,按照m的150%录取,向下取整,如果录取1.5m个向下取整为t,如果后面有人和第t个人的成绩一样,接着录取。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
struct Node{
int a, b;
}P[10000];
bool cmp(Node A, Node B){//sort重载函数
if(A.b == B.b)return A.a < B.a;//成绩一样序号按照从小到大的顺序
else return A.b > B.b;//如果不相等,成绩按照从大到小的顺序
}
int main(){
int n, m;
while(~scanf("%d %d", &n, &m)){
int i;
for(i = 0; i < n; i++){
scanf("%d %d", &P[i].a, &P[i].b);
}
sort(P, P+n, cmp);//sort函数
int total = int(m * 1.5);//录取的人数并且向下取整
int limit = P[total - 1].b;//按照录取的人数划分的界限
int cnt = 0;
for(i = 0; i < n; i++){
if(P[i].b >=limit)cnt++;//统计大于等于这个界限的人数
}
printf("%d %d\n", limit, cnt);
for(i = 0; i < cnt; i++){//输出录取的人的序号,成绩
printf("%d %d\n", P[i].a, P[i].b);
}
}
return 0;
}
P1781 宇宙总统
链接:https://www.luogu.org/problemnew/show/P1781
题意:就是找出最大的那个数,并且这个数的顺序,这个数输出。
题解:方案一:用string类型,根据长度找出最大的长度,然后根据跟最大长度一致的进行字典树大小的比较。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
string a[100], c;
int b[100];
int main(){
int n;
scanf("%d", &n)//不能用多组数据,会有问题的
int i, t, maxn = 0, k;
for(i = 0; i < n; i++){
cin >>a[i];
b[i] = a[i].size();
if(maxn < b[i]){//找最长的一个
maxn = b[i];
k = i;
c = a[i];
}
}
for(i = 0; i < n; i++){//度等于最长的一个,进行字典树比较
if(maxn == b[i]){
if(a[i] > c){
c = a[i];
k = i;
}
}
}
cout<<k+1<<endl;
cout<<c<<endl;
}
方案二:用sort的重载,如果长度不一样,按照长度从大到小的顺序,如果长度一样,按照字典树的从大到小的顺序。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
struct Node{
string s;
int b;
}P[100];
bool cmp(Node A, Node B){
if(A.s.size() != B.s.size())return A.s.size() > B.s.size();
else return A.s > B.s;
}
int main(){
int n;
scanf("%d", &n);
int i;
for(i = 1; i <= n; i++){
cin>>P[i].s;
P[i].b = i;
}
sort(P, P+n, cmp);
cout<<P[0].b<<endl;
cout<<P[0].s<<endl;
return 0;
}