洛谷 P1088 火星人(乱搞)
原创
©著作权归作者所有:来自51CTO博客作者qq639708f19d17e的原创作品,请联系作者获取转载授权,否则将追究法律责任
题目大意:
已知有一串数字,问在原来的数字串的字典序加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;
}