Codeforces Round #653 (Div. 3) 参与排名人数11687
[codeforces 1374F] Cyclic Shifts Sorting 按规则先排最小再排最大
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址http://codeforces.com/contest/1374/problem/F
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
F - Cyclic Shifts Sorting | GNU C++17 | Accepted | 46 ms | 4900 KB |
题目大意:给定元素数量为n的数组a,可做如下操作[ai,ai+1,ai+2]变成[ai+2,ai,ai+1],问能否不超过n^2次操作,使数组a变成自小到大排列的数组。输出操作次数,即每次对应的数组脚标。若不能,输出-1.(反复读题,发现没有说输出最小次数,发现,只要次数不超过n^2即可。)
样例模拟如下:
5
5 4 3 2 1
6
3 1 3 2 2 3
位置3:5 4 (1 3 2)
位置1:(1 5 4) 3 2
位置3:1 5 (2 4 3)
位置2:1 (4 5 2) 3
位置2:1 (2 4 5) 3
位置3:1 2 (3 4 5)
8
8 4 5 2 3 6 7 3
13
2 1 1 6 4 2 4 3 3 4 4 6 6
位置2:8 (2 4 5) 3 6 7 3
位置1:(4 8 2) 5 3 6 7 3
位置1:(2 4 8) 5 3 6 7 3
位置6:2 4 8 5 3 (3 6 7)
位置4:2 4 8 (3 5 3) 6 7
位置2:2 (3 4 8) 5 3 6 7
位置4:2 3 4 (3 8 5) 6 7
位置3:2 3 (8 4 3) 5 6 7
位置3:2 3 (3 8 4) 5 6 7
位置4:2 3 3 (5 8 4) 6 7
位置4:2 3 3 (4 5 8) 6 7
位置6:2 3 3 4 5 (7 8 6)
位置6:2 3 3 4 5 (6 7 8)
6
1 2 3 3 6 4
4
3 3 4 4
位置3:1 2 (6 3 3) 4
位置3:1 2 (3 6 3) 4
位置4:1 2 3 (4 6 3)
位置4:1 2 3 (3 4 6)
样例进一步模拟如下,大体思路,小的一定要排前头,大的一定要排后头。
5
5 4 3 2 1
让1排在第1位
5 4 (1 3 2)
(1 5 4) 3 2
让2排在第2位
1 5 (2 4 3)
1 (4 5 2) 3
1 (2 4 5) 3
让3排在第3位
1 2 (3 4 5)
8
8 4 5 2 3 6 7 3
让2排在第1位
8 (2 4 5) 3 6 7 3
(4 8 2) 5 3 6 7 3
(2 4 8) 5 3 6 7 3
让3排在第2位
2 4 (3 8 5) 6 7 3
2 (8 4 3) 5 6 7 3
2 (3 8 4) 5 6 7 3
让3排在第3位
2 3 8 4 5 (3 6 7)
2 3 8 (3 4 5) 6 7
2 3 (4 8 3) 5 6 7
2 3 (3 4 8) 5 6 7
4已排在第4位
让5排在第5位
2 3 3 4 (6 8 5) 7
2 3 3 4 (5 6 8) 7
6已排在第6位
最后两个数8 7处理不了
让8排在第8位
2 3 3 4 5 (7 6 8)
让7排在第7位
2 3 3 4 (6 5 7) 8
让6排在第6位
2 3 3 (5 4 6) 7 8
让5排在第5位
2 3 (4 3 5) 6 7 8
让3排在第3位
2 (3 3 4) 5 6 7 8
7
5 2 1 6 4 7 3
-1
6
1 2 3 3 6 4
让1排在第1位
1 2 3 3 6 4
让2排在第2位
1 2 3 3 6 4
让3排在第3位
1 2 3 3 6 4
让3排在第4位
1 2 3 3 6 4
最后两个数6 4处理不了
让6排在第6位
1 2 3 (4 3 6)
让4排在第5位
1 2 (3 3 4) 6
对应算法的样例输入输出数据如下:
Input:
5
5
1 2 3 4 5
5
5 4 3 2 1
8
8 4 5 2 3 6 7 3
7
5 2 1 6 4 7 3
6
1 2 3 3 6 4
Output:
0
6
3 1 3 2 2 3
17
2 1 1 3 2 2 6 4 3 3 5 5 6 5 4 3 2
-1
2
4 3
AC代码如下:
#include <stdio.h>
int ans[252000],a[510],tot;
void move(int u){
int t1,t2,t3;
t1=a[u],t2=a[u+1],t3=a[u+2];
a[u]=t3,a[u+1]=t1,a[u+2]=t2;
}
int main(){
int t,n,i,j,mn,mx,u;
scanf("%d",&t);
while(t--){
tot=0;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=1;i<=n-2;i++){
mn=1000;
for(j=i;j<=n;j++)
if(a[j]<mn)mn=a[j],u=j;//找区间[i,n]之间的最小值
while(u>=i+2)ans[++tot]=u-2,move(u-2),u-=2;//最终u的落脚点要么在i,要么在i+1处。
if(u==i+1)move(i),move(i),ans[++tot]=i,ans[++tot]=i;//u的落脚点在i+1处。
}
for(i=n;i>=3;i--){
mx=-1;
for(j=i;j>=1;j--)
if(a[j]>mx)mx=a[j],u=j;
while(u<=i-2)ans[++tot]=u,move(u),u+=2;//最终u的落脚点要么在i,要么在i-1处。
if(u==i-1)move(i-2),ans[++tot]=i-2;//u的落脚点在i-1处。
}
for(i=1;i<n;i++)
if(a[i]>a[i+1])tot=-1;
if(tot==-1)printf("-1\n");
else{
printf("%d\n",tot);
for(i=1;i<=tot;i++)printf("%d ",ans[i]);
printf("\n");
}
}
return 0;
}