洛谷 P1088 火星人(乱搞)

本文介绍了一种解决数字串字典序加m问题的算法。通过逆序搜索和交换数字,确保每次操作后的数字串按字典序递增。详细解释了搜索过程和排序策略,最终实现了在O(m*n*logn)复杂度下找到加m后的数字串。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:

已知有一串数字,问在原来的数字串的字典序加m后,应该输出多少

解题思路:

最简便的做法是用next_permutation,这个生成的全排列可以按照字典序递增,这里我用的是搜索的方法。首先我从后往前搜,一直记录最大值,假如遇到比最大值小的数记为A[j],停止搜索,当前,证明我们可以进行一次交换从而达到加一的效果,那么要找哪个数来完成加一呢?我们再进行同样的搜索过程,记录下比A[j]大的数字里面最小的那一个,记为A[i]。最后完成交换,最后,A[j]之前搜索的数字要从大到小排。

废话:

哎,这种xjb搜索错估了复杂度,其实最后的复杂度只是O(m*n*logn),同时最后的从大到小排也没想过。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int main(){
	int n;cin>>n;
	int m;cin>>m;
	vector<int> arrmv(n);
	for(int i=0;i<n;i++){
		cin>>arrmv[i];
	}
	reverse(arrmv.begin(),arrmv.end());
	for(int i=0;i<m;i++){
		int tmp=arrmv[0];
		int j;
		for(j=1;j<n;j++){
			if(arrmv[j]<tmp)break;
			tmp=max(tmp,arrmv[j]);
		}
		int bsdis=INF;
		int bsidx=-1;
		for(int z=0;z<j;z++){
			if(arrmv[z]>arrmv[j]){
				int tmpdis=abs(arrmv[z]-arrmv[j]);
				if(tmpdis<bsdis){
					bsdis=tmpdis;
					bsidx=z;
				}
			}
		}
		assert(bsidx!=-1);
		swap(arrmv[j],arrmv[bsidx]);
		sort(arrmv.begin(),next(arrmv.begin(),j),greater<int>());
	}
	reverse(arrmv.begin(),arrmv.end());
	for(int i=0;i<(int)arrmv.size();i++){
		if(i)cout<<" ";
		cout<<arrmv[i];
	}
	cout<<endl;
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值