交互+二分——cf1353D

一般交互就跑不出二分。。

但是这题我看了半天才明白啥意思。。最后还fst了

发现有个地方多输出了点东西。。

第一次询问:最大值mx

后面十次询问:二分确定最大值所在位置x

最后一次询问:设x所在si,问出si对应的答案,其他位置的答案都是mx

#include<bits/stdc++.h>
using namespace std;
#define N 2005
 
int n,k,c[N],s[N][N];
 
int ask(int L,int R){
    if(L>R)return 0;
    cout<<"? ";
    cout<<R-L+1<<" ";
    for(int i=L;i<=R;i++)cout<<i<<" ";
    cout<<endl;
    int res;
    cin>>res;
    return res; 
}
int ask1(int x){
    cout<<"? "<<n-c[x]<<" ";
    int tot=0,vis[N]={};
    for(int i=1;i<=c[x];i++)vis[s[x][i]]=1;
    for(int i=1;i<=n;i++)
        if(!vis[i])cout<<i<<" ";
    cout<<endl;
    int res;cin>>res;
    return res;
}
 
int main(){
    int t;cin>>t;
    while(t--){
        cin>>n>>k;
        for(int i=1;i<=k;i++){
            cin>>c[i];
            for(int j=1;j<=c[i];j++)
                scanf("%d",&s[i][j]);
        }
        //问出最大值的下标
        int L=1,R=n,mid,pos=n;
        int mx=ask(1,n);
        while(L<R){
            mid=L+R>>1;
            int res=ask(L,mid);
            if(res==mx)
                R=mid;
            else L=mid+1;
            if(L==R){pos=L;break;}
        } 
        
        int x,ans[N];
        for(int i=1;i<=k;i++)
            for(int j=1;j<=c[i];j++)
                if(s[i][j]==pos)x=i;
        ans[x]=ask1(x);
        
        for(int i=1;i<=k;i++)
            if(i!=x)ans[i]=mx;

        cout<<"! ";
        for(int i=1;i<=k;i++)cout<<ans[i]<<" ";
        cout<<endl;
        string s;
        cin>>s;
    }
}

 

posted on 2020-06-01 14:20  zsben  阅读(152)  评论(0编辑  收藏  举报

导航