题解:AT_arc070_d [ARC070F] HonestOrUnkind
考虑当 \(a\le b\) 的时候,\(a\) 个坏人可以说坏人是好人,这样好人和坏人就无法分辨了,无解。
否则考虑当 \(a>b\) 的时候,我们只要在 \(n\) 次询问内找出一个好人,再用 \(n\) 次询问即可求出所有人的好坏。由于我们只需要一个好人,这启发我们用一个好人换掉一个坏人。这里有一个非常强大的做法,维护一个单调栈状物,栈顶都是好人,栈底都是坏人。每次加入一个人,都向栈顶询问这个人的好坏,则有:
- 如果回答 Yes,则要么两个人都是好人,要么栈顶是坏人,那么直接入栈即可。
- 如果回答 No,则要么栈顶是好人,新来的是坏人,要么栈顶是坏人,则这两个人中定然有一个坏人,把两个人都干掉即可。
考虑每干掉一个坏人,最多只用一个好人,所以最后栈顶一定是一个好人,于是就做完了。
参考资料:ARC070F 题解
Code:
#include<iostream>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,l,r) for(int i=(l);i>=(r);i--)
using namespace std;
const int maxn=4005;
int st[maxn];
char s[maxn],ans[maxn];
void query(int x,int y){
printf("? %d %d\n",x-1,y-1);
fflush(stdout);
scanf("%s",s);
}
int main(){
int ia,ib,in;
cin>>ia>>ib;
in=ia+ib;
if(ia<=ib){
cout<<"Impossible"<<endl;
return 0;
}
int top=0;
rep(v1,1,in){
if(!top){
st[++top]=v1;
continue;
}
query(st[top],v1);
if(s[0]=='Y')st[++top]=v1;
else top--;
}
rep(v1,1,in){
query(st[top],v1);
ans[v1]=(s[0]=='Y')+'0';
}
printf("! %s\n",ans+1);
cin>>in;
return 0;
}

浙公网安备 33010602011771号