标签:Sorting 逆时针 Cyclic int 位置 pos Shifts 操作 2n
F. Cyclic Shifts Sorting(模拟&排序)
传送门
思路: 模拟冒泡排序,只不过两个数交换,变成了三个数进行位置转换。
显然三个数可以顺时针走,也可以逆时针走(顺时针操作两次等价于逆时针操作一次)。
我们可以第i轮将当前最小的数移动到位置i,
因为每操作一次,第三个数可以移动到第一个数的位置。
如果当前最小的数与位置i的距离不是2的倍数,我们需要让位置pos操作一次,使其变为pos+1,然后再不断进行操作fun(pos−2),pos−=2 就可以了。
这里需要注意特判一下,如果当前最小的数在最后一个,直接操作位置n−2,
这样可以在距离不是2的倍数时,向前移动一个位置。
这样我们就可以排好1∼n−2。
接下来特判一下如果a[n−1]≤a[n] 不用再操作了。
否则我们需要将a[n−1],a[n]交换一下位置。
如果a[n−2]=a[n],我们只需对位置n−2操作一次即可。
对于其他情况,显然如果我们只对最后三个数进行操作,无论怎么操作都只会改变相对位置,不会使两个数交换,所以我们要使a[n−1],a[n]交换,我们必须要使a[n−2],a[n−1]交换才行,一直递归,我们必须在前n−2个数找到两个相同的数才行。
ep:a1=1,a2=1,a3=3,a4=2.
显然我们可以对位置1,2分别操作两次(也就是逆时针移动)即可使a3,a4交换。
1,1,3,2→1,3,1,2→1,1,2,3.
时间复杂度:O(n2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e2+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
vector<int>ans;
int a[N];
void fun(int i){
ans.push_back(i);
swap(a[i],a[i+2]),swap(a[i+1],a[i+2]);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
ans.clear();
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n-2;i++){
int pos=i;
for(int j=i;j<=n;j++)
if(a[j]<a[pos]) pos=j;
if(pos==n) pos-=2,fun(pos);
if((pos-i)&1) fun(pos-1),pos++;
while(pos>i) pos-=2,fun(pos);
}
if(a[n-1]>a[n]) {
if(a[n-2]==a[n]) fun(n-2);
else {
for(int i=1;i<n-2;i++) if(a[i]==a[i+1]){
for(int j=i;j<=n-2;j++) fun(j),fun(j);
break;
}
}
}
if(a[n-1]>a[n]){
puts("-1");
continue;
}
printf("%d\n",ans.size());
for(auto i:ans) printf("%d ",i);
puts("");
}
return 0;
}
标签:Sorting,逆时针,Cyclic,int,位置,pos,Shifts,操作,2n 来源: https://blog.csdn.net/weixin_45750972/article/details/107028827
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。