题解 CF1617D2 Too Many Impostors (hard version)
延续 easy version 的思路,找到两个三元组
把原序列每三个元素分一块分成
把
现在我们可以用
代码如下:
//author:望远星
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mk make_pair
#define sml(x,y) (x=min(x,y))
#define big(x,y) (x=max(x,y))
#define ll long long
#define ull unsigned long long
#define db double
#define fo(i,x,y) for(int i=x;i<=y;++i)
#define go(i,x,y) for(int i=x;i>=y;--i)
using namespace std;
inline int read(){int x=0,fh=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-') fh=-1; ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();} return x*fh;}
inline void out(int *a,int l,int r){fo(i,l,r) cout<<*(a+i)<<' ';puts("");}
const int N=1e5+5;
int a[N],n,b[N];
int ask(int x,int y,int z){
printf("? %d %d %d\n",x,y,z);cout.flush();
int ret=read();
if(ret==-1) exit(0);
return ret;
}
void solve(){
cin>>n;int p,q;//p:0 q:1
for(int i=1;i<=n;i+=3){
b[i]=ask(i,i+1,i+2);
if(b[i]) q=i;
else p=i;
}
int x=ask(p+1,p+2,q),y,s,t;
if(x) s=p,t=q;
else{
y=ask(p+2,q,q+1);
if(y) s=p+1,t=q+1;
else s=p+2,t=q+2;
}
//printf("%d,%d\n",s,t);
a[s]=0,a[t]=1;
for(int i=1;i<=n;i+=3){
if(p==i||q==i){
fo(j,i,i+2) if(j!=s&&j!=t) a[j]=ask(s,t,j);
continue;
}
if(b[i]){
if(ask(s,i,i+1)){
a[i]=a[i+1]=1;
a[i+2]=ask(s,t,i+2);
}else a[i+2]=1,a[i]=ask(s,t,i),a[i+1]=a[i]^1;
}else{
if(!ask(t,i,i+1)){
a[i]=a[i+1]=0;
a[i+2]=ask(s,t,i+2);
}else a[i+2]=0,a[i]=ask(s,t,i),a[i+1]=a[i]^1;
}
}
vector<int> ans;fo(i,1,n) if(!a[i]) ans.pb(i);
cout<<"! "<<ans.size()<<' ';for(int i:ans) cout<<i<<' ';puts("");
cout.flush();
}
signed main(){
int T=read();
while(T--) solve();
return 0;
}
/*
-------------------------------------------------
*/