ARC070F HonestOrUnkind 题解
有点厉害的 Ad-hoc
首先如果坏人数量大于等于好人就是分辨不了的,因为其中好人个数个坏人可以互相说是好人,然后说好人是坏人,此时好人的特征和坏人一样了。
首先如果我们能找到一个好人,则只需要 $ n $ 次询问就可以获得所有人的身份。
考虑要尽量缩小好人和坏人的集合。我们考虑维护一个 疑似好人 的集合,每次选择一个未加入的人,然后选择上一个加入的疑似好人出来问即将要加入的人的身份。枚举四种情况。
- 如果疑似好人是好人,回答的是 $ \texttt{Y} $,则新要加入的人是好人。
- 如果疑似好人是好人,回答的是 $ \texttt{N} $,则新要加入的人是坏人。
- 如果疑似好人是坏人,回答的是 $ \texttt{Y} $,则新要加入的人可能是好人也可能是坏人
- 如果疑似好人是坏人,回答的是 $ \texttt{N} $,则新要加入的人可能是好人也可能是坏人。
我们发现如果回答是 $ \texttt{N} $,则当前被拉出来的疑似好人和即将加入的人至少存在一个好人,而好人比坏人多,所以可以直接丢掉这两个人。而当一个好人进入后,只会有好人再进入。因为好人的数量始终大于坏人,所以最后一个加入的一定是好人,此时用了 $ n $ 次询问,再用 $ n $ 次询问判断每个人的身份即可。
代码:
#include<bits/stdc++.h>
#define time(null) chrono::steady_clock::now().time_since_epoch().count()
#define int long long
#define uint unsigned long long
#define debug() cout<<"come here\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define pb push_back
#define Code return
#define by 0
#define MCYYDS ;
using namespace std;
int qpow(int a,int b,int p=INF){int ret=1;while(b){if(b&1)ret=(ret*a)%p;a=(a*a)%p;b>>=1;}return ret;}
inline int read(){int ret=0,f=1;char ch=getchar();while(ch<'0'||ch>'9')f=(ch=='-'?-1:f),ch=getchar();while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();return ret*f;}
inline void write(int x){if(x<0){putchar('-');write(-x);return ;}if(x>9)write(x/10);putchar((char)(x%10+48));}
inline void writech(int x,char ch){write(x);putchar(ch);}
stack<int> stk;
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int a,b;
cin>>a>>b;
if(a<=b)cout<<"Impossible"<<endl;
else
{
stk.push(0);
vector<int> ans(a+b,0);
for(int i=1;i<a+b+a+b;i++)
{
if(stk.empty())
{
stk.push(i);
continue;
}
cout<<"? "<<stk.top()<<' '<<i%(a+b)<<endl;
char c;
cin>>c;
if(c=='Y'&&i<a+b)stk.push(i%(a+b));
else if(c=='Y')ans[i%(a+b)]=1;
else if(i<a+b)stk.pop();
}
cout<<"! ";
for(auto x:ans)
{
cout<<x;
}
cout<<endl;
}
Code by MCYYDS
}

浙公网安备 33010602011771号