题解:CF2134E Power Boxes
分享图片

解析
首先小心不要把“总跳跃次数”看成“总跳跃长度”。
如果你做过前一场的 E,那么你应该很快能想到要把 \(\lceil \frac{3n}{2} \rceil\) 变成 \(n + \lceil \frac{n}{2} \rceil\)。
手玩一下,发现如果设 \(s_i\) 表示从 \(i\) 开始跳的总跳跃次数,当 \(s_{i + 1} \not= s_{i + 2}\) 时,可以通过 \(\texttt{throw } i\) 确定 \(a_i\) 和 \(s_i\) 的值;而当 \(s_{i + 1} = s_{i + 2}\) 时,虽然无法直接确定 \(a_i\) 的值,但是可以得知 \(s_i = s_{i + 1} + 1\)。
这样扫一遍过后,在任意相邻的 \(3\) 个位置上,\(s\) 至少有 \(2\) 种不同的取值。这也意味着对于任意相邻的两个位置,未知的 \(a\) 至多有 \(1\) 个。
太好了,这不就跟 \(\lceil \frac{n}{2} \rceil\) 对上了嘛。于是我们来尝试在两次操作以内求出一个未知的 \(a\)。对于一个位置 \(i\),如果 \(a_i\) 是未知的,那么有 \(s_{i + 1} = s_{i + 2}\) 且 \(a_{i + 1} = 2\)。利用这个性质,只需先 \(\texttt{swap } i\) 再 \(\texttt{throw } i+1\),若得到 \(s_{i + 1}\),则说明 \(a_i=2\),否则 \(a_i=1\)。正着扫一遍就可以求出除 \(a_n\) 外所有的值。
求 \(a_n\) 的方法想必你已经手玩出来了,这里不多赘述。
代码
由于我第二次是倒着扫的,所以还要维护交换后的 \(s\) 和 \(a\),并且需要处理交换导致的对于一个 \(a\) 未知的位置 \(s_{i + 1} \not= s_{i + 2}\) 的情况,换个顺序进行操作可以规避这些问题。
/*
*/
#include<bits/stdc++.h>
#define eps 0.000001
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<ll,int> pii;
const int N = 2e5 + 5,M = 3.2e4 + 5;
ll a[N],stp[N],val[N],vis[N];
int main(){
// freopen("in.txt","r",stdin);
// freopen("out1.txt","w",stdout);
// ios::sync_with_stdio(false);
// cin.tie(0),cout.tie(0);
int T;
cin>>T;
while(T--){
int n;
cin>>n;
stp[n] = 1;
int x;
cout<<"throw "<<n - 1<<endl;
cin>>x;
a[n - 1] = x ^ 3;
cout<<"swap "<<n - 1<<endl;
cout<<"throw "<<n - 1<<endl;
cin>>x;
a[n] = x ^ 3;
val[n - 1] = a[n],val[n] = a[n - 1];
stp[n - 1] = x;
stp[n + 1] = 0;
for(int i=n - 2;i>=1;i--){
if(stp[i + 1] != stp[i + 2] && stp[i + 2]){
int x;
cout<<"throw "<<i<<endl;
cin>>x;
stp[i] = x;
if(x == stp[i + 2] + 1) a[i] = 2;
else a[i] = 1;
val[i] = a[i];
}else{
stp[i] = stp[i + 1] + 1;
}
}
for(int i=n - 2;i>=1;i--){
if(!a[i]){
if(stp[i + 1] != stp[i + 2]){
int x;
cout<<"throw "<<i<<endl;
cin>>x;
stp[i] = x;
if(x == stp[i + 2] + 1) a[i] = 2;
else a[i] = 1;
val[i] = a[i];
continue;
}
int x,y;
x = stp[i + 1];
cout<<"swap "<<i<<endl;
cout<<"throw "<<i + 1<<endl;
cin>>y;
val[i] = val[i + 1];
val[i + 1] = a[i] = y == x ? 2 : 1;
stp[i + 1] = y;
stp[i] = stp[i + val[i]] + 1;
}else{
stp[i] = stp[i + a[i]] + 1;
}
}
cout<<"! ";
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
a[i] = stp[i] = val[i] = 0;
}
cout<<endl;
}
return 0;
}
/*
*/

浙公网安备 33010602011771号