洛谷题单【算法1-2】排序(STL应用cpp版)

本人发的第一篇啦,第一次写不足之处多多见谅。

前几天练stl排序算法,感觉还不错欸~~

题单索引:【算法1-2】排序 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/training/107#information

一,基本应用(咋排序啊)

1.sort函数类:

头文件:

#include<algorithm>

(1)sort:

sort(first,last,comp)

对[first, last)范围内的元素按comp规则进行排序。

注意:排序的范围[first, last),包括first,不包括last。

对于comp:

less:小于,默认值,可不写,升序排序
greater:大于,降序排序
less_equal:小于等于
greater_equal:大于等于
也可以自定义比较函数。

举个例子:

#include<bits/stdc++.h>
using namespace std;
bool my_less(int i, int j) {return (i< j);}//自定义小于
bool my_greater(int i, int j) {return (i> j);}//自定义大于
int main ()
{
int a[]={1,3,8,2,6,2,5,4};
sort(a+2,a+6); //对4个数排序,结果:1 3 2 2 6 8 5 4
sort(a,a+8,less<int>()); //结果:1 2 2 3 4 5 6 8
sort(a,a+8,my_less); //自定义排序,结果:1 2 2 3 4 5 6 8
sort(a,a+8,greater<int>());//从大到小排序,结果:8 6 5 4 3 2 2 1
sort(a,a+8,my_greater); //结果:8 6 5 4 3 2 2 1
stable_sort(a+3,a+8); //结果:8 6 5 1 2 2 3 4
return 0;
}

luogu提供了模板题呢:

P1177: P1177 【模板】排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int main()
{
    vector<int> a;
    int n,i;
    cin>>n;
    for(i=0;i<n;i++)
    {
        int x;
        cin>>x;
        a.push_back(x);
    }
    sort(a.begin(),a.end());
    for(i=0;i<n;i++)
    cout<<a[i]<<" ";
    
    return 0;
}

简单的哒~

(2)stable_sort

stable_sort(first, last, comp)

stable在字面意思上讲就是稳定哒!qwq

和sort()相似,不同之处在于,对于[first, last) 范围内值相同的元素,不会改变它们的相对位置(保持原输入顺序)。

比如说:

4 2 6 3 5 2 1(红色为第一个2,蓝色为第二个2)

1 2 2 3 4 5 6

(3)partial_sort

partial_sort(first, middle, last, comp)

是部分嘛~~

以交换元素存储位置的方式实现部分排序,将[first, last) 范围内最小(或最大)的 middle-first 个元素移动到 [first, middle) 区域中,并对这部分元素做升序(或降序)排序。

比如说:partial_sort(a,a+3,a+7);

4 2 6 3 5 7 1

1 2 3 6 5 7 4

(4)nth_element

nth_element(first, nth, last, comp) 

采用默认的升序时,该函数从某个序列中找到第k小的元素e(序列下标从0开始),并将e移动到序列中第k的位置处(默认是求区间第k小的)。而且,整个序列经过nth_element()函数处理后,所有位于e之前的元素都比e小,所有位于e之后的元素都比e大。

比如说:nth_element(a,a+k,a+n)

把下标为k的元素放在正确位置,对其它元素并没有排序,且k左边元素都小于等于它,右边元素都大于等于它,因此可利用这个函数快速定位某个元素。

比如说:nth_element(a,a+n-k,a+n)
将下标为n-k,也就是第n-k+1个数放在正确的位置,求的是第k大的数a[n-k]。

luogu有呢:

P1923 :P1923 【深基9.例4】求第 k 小的数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

第一次做时看这个题不让用nth_element,这是啥啊 ??? *-*

既然学到了就看看咋用呗,先学会了再手搓原理。。。

#include<iostream>
#include<cstdio> 
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	int n,m;
	cin>>n>>m;
	vector<int> e; 
	for(int i=0;i<n;i++)
	{
		int f;
		cin>>f;
		e.push_back(f);
	}
	
	nth_element(e.begin(),e.begin()+m,e.end());
	printf("%d",e[m]);
	return 0;
}
	

(5)is_sorted

is_sorted(first, last, comp) 

用的不多呐。。。

检测 [first, last) 范围内是否已经排好序,默认检测是否按升序排序。

判断一下:

#include<bits/stdc++.h>
using namespace std;
int main ()
{
    int b[]={3,7,2,5,6,8,5,4};
    partial_sort(b,b+3,b+8); //结果:2 3 4 7 6 8 5 5
    partial_sort(b,b+3,b+8,greater<int>()); //结果:8 7 6 2 3 4 5 5

    if (is_sorted(b,b+3,greater<int>()))
    cout<<"is sorted"<<endl; //输出:is sorted
    
    //排动态数组:
    vector<int> c = {1,2,3,4,5,6,7,8};//C11
    sort(c.begin(),c.end(),my_greater); //结果:8 7 6 5 4 3 2 1
    
    //排字符串
    string s="hello world";
    sort(s.begin(),s.end(),greater<char>());
    cout<<s<<endl;//输出: wroolllhed注意最后一个是空格
    
    return 0;
}

2.set函数类:

头文件:

#include<set>

set就是集合,STL的set用二叉树实现,集合中的每个元素只出现一次(参照数学中集合的互斥性),并且是排好序的(默认按键值升序排列)。

也就是说,这玩意儿又能去重又能排序嘿嘿~~

附上链接:c++ set用法详解-CSDN博客

3.优先队列:

头文件:

#include<queue>

可以做到一边插入一边排序,挺快的。(写过用sort超时但优先队列不超时的程序,呜呜哭死)

懒得讲了。。看大佬代码偷学会的,可以看看其他大佬的博客。

附上链接:【原创】优先队列 priority_queue 详解-CSDN博客

二,刷luogu(🤮)
 

不就是个排序嘛,有啥难的。。。

P1271:P1271 【深基9.例1】选举学生会 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

简简单单的排序应用,学生会定律对吧。。。

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int a[2000000],n,m,i;
    
    scanf("%d%d",&n,&m);
    
    for(i=0;i<m;i++)
        scanf("%d",&a[i]);
    
    sort(a,a+m);
    
    for(i=0;i<m;i++)
        printf("%d ",a[i]);
    
    return 0;
}

P1059:P1059 [NOIP2006 普及组] 明明的随机数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

嗨嗨嗨,这不set超简单嘛~

#include<iostream>
#include<cstdio> 
#include<string>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	set<int> e;
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		int a;
		cin>>a;
		e.insert(a);//插入元素
	}
	int l=e.size();
	printf("%d\n",l);//去重了,输出个数
	for(auto it:e)
	{
		printf("%d ",it);//输出
	}
	return 0;
}
	

P1093:P1093 [NOIP2007 普及组] 奖学金 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

用优先队列写的,记得一定看好排序规则哈~~(有个样例终于改对了呜呜)。。。

其实也不用这么麻烦🙂。。。

#include<iostream>
#include<cstdio> 
#include<string>
#include<vector>
#include<set>
#include<queue> 
#include<algorithm>
using namespace std;
struct stud{
	int id;
	int ch;
	int ma;
	int en;
	int sum;
	friend bool operator<(stud a,stud b)
	{
		if(a.sum==b.sum)
		{
			if(a.ch==b.ch)
			return a.id>b.id;
			else
			return a.ch<=b.ch;
		}
		return a.sum<=b.sum;
	}
};

priority_queue<stud> e; 

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		e.push({i+1,a,b,c,a+b+c});
	}
	
	int cn=0;
	while(!e.empty())
	{
		stud it=e.top();
		cout<<it.id<<" "<<it.sum<<endl;
		cn++;
		if(cn==5)
		break;
		e.pop();
	}
	
	return 0;
}
	

P1781:P1781 宇宙总统 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

哦~我亲爱的孩子,为啥不是牢大?(我没意见)

注意一下这个字符串型的数字如何判断大小,我记得当初从高精度减法偷学的。。。

#include<iostream>
#include<cstdio> 
#include<string>
#include<vector>
#include<set>
#include<queue> 
#include<algorithm>
using namespace std;
struct stud{
	string s;
	int id;
	friend bool operator <(stud a,stud b)
	{
		return a.s.size()<b.s.size()||a.s.size()==b.s.size()&&a.s<b.s;
	}
};

int main()
{
	ios::sync_with_stdio(0);
	priority_queue<stud> e;
	cin.tie(0);
	cout.tie(0);
	int n;
	cin>>n;cin.ignore();
	for(int i=0;i<n;i++)
	{
		string ss;
		cin>>ss;
		e.push({ss,i+1});
	}
	auto it=e.top();
	cout<<it.id<<endl<<it.s;
	return 0;
}
	

P2676:P2676 [USACO07DEC] Bookshelf B - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

入门题,注意降序排列(也可以升序排则倒着找)。

#include<iostream>
#include<cstdio> 
#include<string>
#include<vector>
#include<set>
#include<queue> 
#include<algorithm>
using namespace std;
int main()
{
	ios::sync_with_stdio(0);

	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin>>n>>m;
	vector<int> s(n+10,0);
	
	for(int i=0;i<n;i++)
	cin>>s[i];
	
	sort(s.begin(),s.end(),greater<int>());
	int sum=0,cn=0;
	for(int i=0;i<n;i++)
	{
		sum+=s[i];
		cn++;
		if(sum>m)
		break;
	}
	cout<<cn;
	return 0;
}
	

P1116:P1116 车厢重组 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

冒泡排序呢。

#include<iostream>
#include<queue> 
#include<algorithm>
using namespace std;
int sum;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	int n;
	cin>>n;
	vector<int> s(n+10,0);
	
	for(int i=0;i<n;i++)
	cin>>s[i];
	
	for(int i=0;i<n-1;i++)
		for(int j=i+1;j<n;j++)
			if(s[i]>s[j])
			{
				sum++;
				swap(s[i],s[j]);
			}
	
    cout<<sum;
	return 0;
}
	

P1152:P1152 欢乐的跳 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

暴力找,然后排序呗,最后判断过程记得剪枝。

#include<iostream>
#include<cmath> 
#include<vector>
#include<algorithm>
using namespace std;


int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	int n;
	cin>>n;
	vector<int> s(n+10,0),v;
	
	for(int i=0;i<n;i++)
	cin>>s[i];
	
	for(int i=1;i<n;i++)
		v.push_back(abs(s[i]-s[i-1])); 
	
	sort(v.begin(),v.end());
	
	for(int i=0;i<v.size();i++)
	{
		if(v[i]!=i+1)
		{
			printf("Not jolly\n");
			return 0;
		}//判断输出 
	}
    
    printf("Jolly\n");//如果未能输出,则为正确答案
    return 0;//过程结束
}

	

P1068:P1068 [NOIP2009 普及组] 分数线划定 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

优先队列写累了,这次结构体排序写法。。。

#include<iostream>
#include<cmath> 
#include<vector>
#include<algorithm>
using namespace std;
struct stud
{
	string id;
	int gra;	
}stu[100001];

bool cmp(struct stud a,struct stud b)
{
	if(a.gra==b.gra)
	return a.id<b.id;
	
	return a.gra>b.gra;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		cin.ignore();
		cin>>stu[i].id>>stu[i].gra;
	}
	
	sort(stu,stu+n,cmp);//排序 
	
	int line=m*1.5;//找出分数线 
	cout<<stu[line-1].gra<<" ";
	
	int cn=0;
	for(int i=0;i<n;i++)
	{
		if(stu[i].gra>=stu[line-1].gra)
		cn++;
		else
		break;
	}//记录个数 
	
	cout<<cn<<endl;
	for(int i=0;i<cn;i++)
	cout<<stu[i].id<<" "<<stu[i].gra<<endl;
	return 0; 
}

	

P5143:P5143 攀爬者 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这不就是计算题,乐~(义务教育上个寂寞qwq)

坐标中直线距离算出来相加哈。。。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
struct dir
{
	int x,y,z;
}a[50001];
bool cmp(struct dir x,struct dir y)
{
	return x.z<y.z;
}

int n;
double ans;

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i].x>>a[i].y>>a[i].z;
	
	sort(a+1,a+n+1,cmp);
	
	for(int i=2;i<=n;i++)
		ans+=sqrt((a[i-1].x-a[i].x)*(a[i-1].x-a[i].x)+(a[i-1].y-a[i].y)*(a[i-1].y-a[i].y)+(a[i-1].z-a[i].z)*(a[i-1].z-a[i].z));//题意给的公式,sqrt是开根号
	
	printf("%.3lf",ans);
   return 0;
}

 P1104:P1104 生日 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 啥时候给我生日礼物(滑稽doge)

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue> 
#include<iostream>
using namespace std;

struct birthday
{
	string name;
	int year,mon,day,id;
	friend bool operator <(struct birthday x,struct birthday y)
	{
		if(x.year==y.year) 
		{
			if(x.mon==y.mon)
			{
				if(x.day==y.day)
				return x.id<y.id;
				
				return x.day>y.day;
			}
			return x.mon>y.mon;
		}
		return x.year>y.year;
	}
};


int main()
{
	
	int n;
	cin>>n;
	cin.ignore();
	priority_queue<birthday> e;
	
	for(int i=0;i<n;i++)
	{
		string ss;
		int a,b,c;
		cin>>ss>>a>>b>>c;
		e.push({ss,a,b,c,i});
	}
	
	while(!e.empty())
	{
		cout<<e.top().name<<endl;
		e.pop();
	}
	return 0;
}  

P1012:P1012 [NOIP1998 提高组] 拼数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这题有点不好想啊,为贪心思想

对贪心正确性的证明:
分析可见两同样长字符串a和b,若a比b大,必有x使得 a在x位第一次b大 。

说明前面的位大,就可以忽略后面的位,可以贪心解决,把对字典序贡献最大的放在前面。比较方法只要比较 a+b和b+a的大小即可。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue> 
#include<iostream>
using namespace std;
bool cmp(string s1,string s2)
{
	return s1+s2>s2+s1;
}
int main()
{
	int n;
	string s[2000];
	cin>>n;
	
	for(int i=0;i<n;i++)
	cin>>s[i];
	
	sort(s,s+n,cmp);
	
	for(int i=0;i<n;i++)
	cout<<s[i];
	return 0;
}  

结束辣,感谢阅读!!!!

第一次写的不好,见谅见谅呜呜。。。
 

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值