昨天晚上巨困,就没有打,今天课间的时候就看了一下D题,发现好像可以瞎搞,于是吃完饭就写了一下,调过样例一次就A了qaq。
D. Sequence and Swaps
枚举+贪心
由于数据范围n≤500n\leq500n≤500,由此我们可以在n3n^3n3完成此题。
最后完成所有操作后,我们手中肯定还有一个数,我们考虑去枚举这个数。
最后手里的数一定不在最终的排列中,于是用一个数组b[]
把除了手中的数记录下来,不难发现只要排序一下这个所有数的位置就确定了。
而且不难发现如果当前手中的数是xxx,我们必须一次将他归位,于是就模拟操作,每次找出现在手中的数在b[]
数组中的位置(注意重复的数只需要开一个st[]
数组记录一下即可),然后看看能不能执行交换操作,把过程模拟一边,顺便记录次数。
模拟过程中,如果当前手中的数已经是枚举剩余的数之间跳出循环,如果不能交换说明不合法也直接跳出循环。
最后再判断一下是否满足条件即可。
时间复杂度O(n3)O(n^3)O(n3)
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=510;
int a[N],b[N],c[N];
bool st[N];
int main()
{IO;int T=1;cin>>T;while(T--){int n,x;cin>>n>>x;for(int i=1;i<=n;i++) cin>>a[i];bool fl=1;for(int i=2;i<=n;i++)//特判最后手中的数是 x 也就是不用操作if(a[i]<a[i-1]) fl=0;if(fl) {cout<<0<<'\n';continue;}a[n+1]=x;int res=0x3f3f3f3f;for(int i=1;i<=n;i++)// 枚举剩下的数是a[i]{for(int j=1;j<=n;j++){if(i==j)b[j]=x;elseb[j]=a[j];}sort(b+1,b+1+n);int tmp=x;memcpy(c,a,sizeof c);bool ok=1;int cnt=0;for(int j=1;j<=n;j++){memset(st,0,sizeof st);int k;for(k=1;k<=n;k++)// 找到当前手中的数应该所在的位置{if(b[k]==tmp&&c[k]!=tmp){while(st[k]||c[k]==tmp) k++;st[k]=1;break;}}if(c[k]>tmp) // 能不能执行交换操作{swap(c[k],tmp);cnt++;if(tmp==a[i]) break;//手中的数已经是枚举的数}else// 交换失败{ok=0;break;}}for(int i=2;i<=n;i++)if(c[i]<c[i-1]) ok=0;if(a[i]!=tmp) ok=0;// 最后手中的数tmp一定要等于枚举的数a[i]if(ok) res=min(res,cnt);}if(res==0x3f3f3f3f) cout<<-1<<'\n';else cout<<res<<'\n';}return 0;
}
感觉应该有复杂度更优的做法,但是我这个做法若优化感觉十分难写~~
要加油哦~