Codeforces Round #646 (Div. 2)D. Guess The Maximums(交互题+二分)

题目:click
题意:题目是真滴长。。。,简而言之,将A数组中挑选出k个两两取交集都是空集的集合,k位的密码,对应k个集合,是除自己集合以外的数字的最大值就是该位的密码。

注意题目中说了最多12次询问,n的范围是1000,可知log(n)一定可以,并且还多余了两次询问机会,第一次去找A数组中1-n的最大值记录下来,之后我们取二分询问出最大值在A数组的下标,最后一次询问就是最大值下标所在此集合,问除此集合里面的数字其余下标在A数组中的最大值,注意一点可能最大值没有挑选进入 S i S_i 集合中,密码则全是最大值。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
int a[1010][1010];
int siz[1010],ans[1010];
int query(int x)
{
    printf("?");
    printf(" %d",x);
    for(int i=1;i<=x;i++)
    {
        printf(" %d",i);
    }
    printf("\n");
    cout.flush();
    int ans;
    scanf("%d",&ans);
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,k,i,j;
        scanf("%d %d",&n,&k);
        for(i=1;i<=k;i++)
        {
            scanf("%d",&siz[i]);
            for(j=1;j<=siz[i];j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        printf("? %d",n);
        for(i=1;i<=n;i++)
        {
            printf(" %d",i);
        }
        printf("\n");
        cout.flush();
        int MAX;
        scanf("%d",&MAX);
        int l=1,r=n;
        int res=1;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(query(mid)==MAX)
            {
                r=mid-1;
                res=mid;
            }
            else
                l=mid+1;
        }
    int temp=-1;
    memset(ans,0,sizeof(ans));
    for(i=1;i<=k;i++)
    {
        bool flag=false;
        for(j=1;j<=siz[i];j++)
        {
            if(a[i][j]==res)
            {
                flag=true;
                temp=i;
            }
        }
        if(!flag)
        {
            ans[i]=MAX;
        }
    }
    if(temp!=-1)
    {
        map<int,int>hh;
        for(j=1;j<=siz[temp];j++)
        {
            hh[a[temp][j]]=1;
        }
        printf("? ");
        printf("%d ",n-siz[temp]);
        for(i=1;i<=n;i++)
        {
            if(hh[i])
                continue;
            else
            {
                printf("%d ",i);
            }
        }
        printf("\n");
        cout.flush();
        scanf("%d",&ans[temp]);
    }
    printf("! ");
    for(i=1;i<=k;i++)
    {
        printf("%d ",ans[i]);
    }
    printf("\n");
    cout.flush();
    string anss;
    scanf("%s",anss.c_str());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/106503769