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

題目鏈接

題目大意

讀了我一個世紀

給你一個長爲n的數組和k個有關數組下標的集合,每個集合告訴你這個集合的大小,以及每個集合所包含數組的下標。這k個集合都沒有交集,要你找出k個ans,ans就是除了這個集合外,所有數組的最大值。

你有最多12次詢問,每次詢問就是你可以查詢任意自己組合的集合的最大值。

n<=1000

題目思路

看這個數據範圍就知道是要二分,首先你會發現,這k個值,要麼都是max(a[i]),要麼有一個不是,首先用一次查詢找出max(a[i]),再用10次以內的查詢二分max(a[i])的下標,判斷每個集合是否有這個下標,如果沒有直接輸出-1,如果有的話,那麼就直接查詢這個集合的補集的最大值作爲這個答案即可。正好最多12次真是妙不可言

代碼

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+5;
int t,n,k,subset[maxn][maxn],num[maxn],ma;
bool mp[maxn];//標記
void query(int l,int r){
    printf("? %d ",r-l+1);
    for(int i=l;i<=r;i++){
        printf("%d ",i);
    }
    fflush(stdout);
}
int main(){
	scanf("%d",&t);
	while(t--){
        memset(mp,0,sizeof(mp));
        scanf("%d %d",&n,&k);
        for(int i=1;i<=k;i++){
            scanf("%d",&num[i]);
            for(int j=1;j<=num[i];j++){
                scanf("%d",&subset[i][j]);
            }
        }
        query(1,n);
        scanf("%d",&ma);//詢問最大值
        int l=1,r=n,pos=-1,x;//找ma的位置
        while(l<=r){
            int mid=(l+r)/2;
            query(l,mid);
            cin>>x;
            if(x==ma){//ma在[l,mid]裏面
                pos=mid;
                r=mid-1;
            }else{
                l=mid+1;
            }
        }
        int spe=-1,spema;//找可能最大值不是ma的那個集合
        for(int i=1;i<=k;i++){
            for(int j=1;j<=num[i];j++){
                if(subset[i][j]==pos){//查詢這個集合在[1,n]的補集
                    spe=i;
                    for(int k=1;k<=num[i];k++){
                        mp[subset[i][k]]=-1;
                    }
                    printf("? %d ",n-num[i]);
                    for(int k=1;k<=n;k++){
                        if(mp[k]==0){
                            printf("%d ",k);
                        }
                    }
                    fflush(stdout);
                    scanf("%d",&spema);
                }
            }
        }
        printf("! ");
        for(int i=1;i<=k;i++){
            if(i!=spe){
                printf("%d ",ma);
            }else{
                printf("%d ",spema);
            }
        }
        fflush(stdout);
        char s[20];
        scanf("%s",s);
	}
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章