[题解]CF1374F Cyclic Shifts Sorting
与 @Zelotz duel,苦战 129min AC。
思路
(本文中默认字符的大小顺序为:)
首先发现不关心最后两个数是否合法,将前 个位置变得递增是容易的。具体的,对于每一个位置 ,在最终的序列中的值记为 ,那么在当前序列中找到一个位置 ,使得 。这时候我们就可以将 暴力往前跳,需要注意的是当 奇偶不同时,在最后一步需要操作两次。
若现在最后两个数 则直接合法了,否则只需考虑将最后两个数交换一下。手玩一下 的样例,注意到形如 aba
的串只需操作一次 即可合法。推广到 ,若最后三位形如 aba
则通过操作一次 即可。
其次,观察最后一个样例,它出现了形如 aacb
的结构,通过操作两次 ,两次 将串变成了 aabc
。这启示我们如果能让 cb
贴上一个 aa
,就可以换成 bc
。
不妨找到一个 使得 ,若找不到一定无解。我们只需将最后两个数移动到 的位置上,做一次 aacb
,然后再移回去。
具体的,你发现若两个点 奇偶性相同,则 能通过一直操作达到 ;否则,需要调整一下 的奇偶再移动。若 和 奇偶不同,操作两次 ,即可将最后两个数分别移到 ,此时可以直接移动。
若回来的时候奇偶不同,同理操作两次 再移动即可。因为前面将 个数操作的步数带 的常数,所以若有解按照上述操作方式一定能在 次操作中变化成功。
Code
#include <bits/stdc++.h>
#define re register
using namespace std;
const int N = 510;
int n;
int arr[N],tmp[N];
vector<int> ans;
inline int read(){
int r = 0,w = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-') w = -1;
c = getchar();
}
while (c >= '0' && c <= '9'){
r = (r << 3) + (r << 1) + (c ^ 48);
c = getchar();
}
return r * w;
}
inline void move(int x){
ans.push_back(x);
int a = arr[x],b = arr[x + 1],c = arr[x + 2];
arr[x] = c; arr[x + 1] = a; arr[x + 2] = b;
}
inline void gopre(int a,int b){
while (a - 2 >= b) move(a - 2),a -= 2;
if (a != b) move(b),move(b);
}
inline void gonxt(int a,int b){
while (a != b) move(a),move(a),a += 2;
}
inline void solve(){
ans.clear(); n = read();
for (re int i = 1;i <= n;i++) arr[i] = tmp[i] = read();
sort(tmp + 1,tmp + n + 1);
for (re int i = 1;i <= n - 2;i++){
int id = 0;
for (re int j = i;j <= n;j++){
if (arr[j] == tmp[i]){
id = j; break;
}
}
gopre(id,i);
}
if (arr[n - 1] > arr[n]){
if (arr[n] == arr[n - 2]) move(n - 2);
else{
int id = -1;
for (re int i = 1;i < n;i++){
if (arr[i] == arr[i + 1]) id = i + 2;
}
if (!~id) return puts("-1"),void();
int a = n - 1,b = n;
if ((n - 1) % 2 != id % 2){
move(n - 2); move(n - 2);
a = n - 2; b = n - 1;
}
gopre(a,id); gopre(b,id + 1);
move(id - 2); move(id - 2);
move(id - 1); move(id - 1);
if ((n - 1) % 2 == id % 2){
gonxt(id + 1,n); gonxt(id,n - 1);
}
else{
move(id - 1); move(id - 1);
gonxt(id,n); gonxt(id - 1,n - 1);
}
}
}
if (ans.size() > n * n) puts("-1");
else{
printf("%d\n",ans.size());
for (int x:ans) printf("%d ",x); puts("");
}
}
int main(){
int T; T = read();
while (T--) solve();
return 0;
}
作者:WaterSun
出处:https://www.cnblogs.com/WaterSun/p/18575320
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】