CF1561E - Bottom-Tier Reversals——有趣的构造题
看题解才做出来,整理一下。
第一步
由于只能翻转奇数前缀,所以对于所有数翻转前后下标奇偶性不变。
通过此,判断如果 \(i\) 的奇偶性异于 \(a_i\) 的奇偶性,则无解。
第二步
由于只能翻转 \(a_i\) 为奇数的前缀,所以猜想相邻的两个数一起考虑,即:先处理 \(1,2\),让它们处理完后变成 xxxx,2,1;再处理 \(3,4\),……;再处理 \(2i-1,2i\),让它们处理完后变成 xxxx,2i,2i-1,2i-2,2i-3,...,2,1;最后处理 \(n-2,n-1\),那么已经不需要处理 \(n\) 了,最后排成 n,n-1,...,2,1,只需再用一次翻转操作翻转整个数列。
通过此,猜想每一步至多翻 5 次,因为 \(5\lfloor\frac{n}{2}\rfloor+1\le\frac{5n}{2}\),6 就不行了。
第三步(翻转策略)
假如现在是这么一个状态
xxx,2i-1,xxx,2i,xxx,2i-2,...,2,1
为了叙述方便,记 \(p1,p2\) 为 \(2i-1,2i\) 的位置。
- 翻转 \([1,p1]\):
2i-1,xxx,2i,xxx,2i-2,...,2,1 - 翻转 \([1,p2-1]\):
xxx,2i-1,2i,xxx,2i-2,...,2,1 - 翻转 \([1,p2+1]\):
x,2i,2i-1,xxx,2i-2,...,2,1
这里做一解释,由于 \(2i\) 此时坐标为偶,所以翻的是 \(p2+1\),由于 \(2i-2\) 的坐标也是偶的,所以 \(2i\) 和 \(2i-2\) 之间肯定有一个x(代表不相干数),因此不会影响到 \(2i-2\) 那一块。 - 翻转 \([1,3]\):
2i-1,2i,x,xxx,2i-2,...,2,1 - 最后,翻转 \([1,pos(2i-2)-1]\)(\(pos\) 代指数值的位置):
xxx,2i,2i-1,2i-2,...,2,1
共 5 次。
可以自己思考一下 xxx,2i,xxx,2i-1,xxx,2i-2,...,2,1 的情况,操作序列是不变的,但注意 \(p1,p2\) 在每一次翻转之后是可能发生变化的。
代码
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N=2025;
int n,a[N],pos[N];
void rev(int m){
printf("%d ",m);
for(int i=1;i<=m/2;i++)swap(a[i],a[m-i+1]);
for(int i=1;i<=m;i++)pos[a[i]]=i;
}
void solve(){
cin>>n;
bool noans=0;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]&1^i&1)noans=1;
pos[a[i]]=i;
}
if(noans){puts("-1");return;}
cout<<n/2*5+1<<'\n';
pos[0]=n+1;
for(int i=1;i<n;i+=2){
rev(pos[i]),rev(pos[i+1]-1),rev(pos[i+1]+1),rev(3),rev(pos[i-1]-1);
}
printf("%d\n",n);
}
int main(){
int t;cin>>t;while(t--)solve();
}
想想看,这个为什么错了
#include <bits/stdc++.h>
using namespace std;
const int N=2025;
int n,a[N],pos[N];
void rev(int m){
for(int i=1;i<=m/2;i++)swap(a[i],a[m-i+1]);
for(int i=1;i<=m;i++)pos[a[i]]=i;
}
void solve(){
cin>>n;
bool noans=0;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]&1^i&1)noans=1;
pos[a[i]]=i;
}
if(noans){puts("-1");return;}
cout<<n/2*5+1<<'\n';
pos[0]=n+1;
for(int i=1;i<n;i+=2){
printf("%d %d %d %d %d ",pos[i],pos[i+1]-1,pos[i+1]+1,3,pos[i-1]-1);
rev(pos[i]),rev(pos[i+1]-1),rev(pos[i+1]+1),rev(3),rev(pos[i-1]-1);
}
printf("%d\n",n);
}
int main(){
int t;cin>>t;while(t--)solve();
}

浙公网安备 33010602011771号