T2 Game 题解
为了方便,设
首先考虑
如果
如果
接着考虑先手:
- 如果刚开始
a_1=n ,先手的最优策略显然是将这个数移走,这样后手只能把这个数移回来。否则,后手可能在后面找到一个比原来字典序更大的方案。这样,最终得到的答案会和刚开始的排列完全相同。 - 如果
a_1\ne n ,先手不会傻到去交换位置1 和p_n 。因此后手的操作肯定是交换先手操作后的位置1 和p_n 。可以发现,在这种情况下,等价于后手先交换现在的位置1 和p_n ,先手再按最优方式操作(这个证明比较显然,能够自己理解的可以直接跳过下面一段):- 如果先手的操作不涉及位置
1 和p_n ,那么这两个操作先后显然是无关的。 - 如果先手交换了位置
1 和i ,后手交换新的位置1 和p_n ,那么现在的情况是位置1 变成了n ,位置i 变成了a_1 ,位置p_n 变成了a_i 。可以发现这种情况和先交换位置1 和p_n ,再交换(原来的)位置p_n 和i 是等价的。 - 先手交换位置
p_n 和i 的情况同理。
- 如果先手的操作不涉及位置
- 因此在这种情况下,可以直接交换位置
1 和p_n ,剩下的问题是位置2\sim n 里面交换两个数使得字典序最小,就变成了前面t=1 时讨论的方法。
代码模拟,不难做到
现在考虑
对于
对于
那么就可以把
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N],p[N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
long long t;int n;cin>>t>>n;
for(int i=1;i<=n;i++)cin>>a[i],p[a[i]]=i;
if(t&1){
for(int i=1;i<=n;i++){
if(a[i]!=i){
swap(a[i],a[p[i]]);
break;
}
}
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
}else{
if(a[1]==n){
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
}else{
p[a[1]]=p[n];
swap(a[1],a[p[n]]);
p[n]=1;//这句实际可以删掉
for(int i=2;i<=n;i++){
if(a[i]!=i-1){
swap(a[i],a[p[i-1]]);
break;
}
}
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
}
}
return 0;
}