CF 1363 D. Guess The Maximums

交互題,看數據範圍,鐵定二分。設這n個元素最大值爲mx。

問每個集合的補集最大值,顯然,要麼全是mx,要麼只有一個不是mx。

(最大值在某個集合裏,那其他集合的補集最大值一定是mx,這個集合的補集最大值再單獨進行依次詢問即可。(有可能其他集合也有mx))

所以先第一次詢問mx,然後花10次詢問mx最小的id。然後遍歷判斷是否有集合中含有id,如果都沒有,顯然結果都是mx。

如果其中一個含有mx,則詢問這個集合的補集最大值即可。最多12次詢問。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e3+7;

int vs[M];
void ask(int l,int r)
{
	
	cout<<"? "<<r-l+1;for(int i=l;i<=r;i++)cout<<" "<<i;cout<<endl;
}
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		vector<int>s[1100];
		int n,k;
		cin>>n>>k;
		for(int i=1;i<=k;i++)
		{
			int m,x;cin>>m;
			for(int j=1;j<=m;j++)cin>>x,s[i].pb(x);
		}
		ask(1,n);
		int mx;
		cin>>mx;
		int l=1,r=n;
		while(l<r)
		{
			int mid=(l+r)/2;
			ask(l,mid);
			int tp;
			cin>>tp;
			if(tp==mx)r=mid;
			else l=mid+1;
		}
		bool f=false;
		int id,p;
		for(int i=1;i<=k;i++)
		{
			
			for(auto x:s[i])
			{
				if(x==l)
				{
					id=i;
					f=true;
					break;
				}
			}
			if(f)break;
		}
		for(int i=1;i<=n;i++)vs[i]=0;
		for(auto x:s[id])vs[x]=1;
		cout<<"?";
		int nm=0;
		for(int i=1;i<=n;i++)if(!vs[i])nm++;
		cout<<" "<<nm;
		for(int i=1;i<=n;i++)if(!vs[i])cout<<" "<<i;
		cout<<endl;
		cin>>p;
		cout<<"!";
		for(int i=1;i<=k;i++)
		{
			if(i!=id)cout<<" "<<mx;
			else cout<<" "<<p;
		}
		cout<<endl;
		string z;
		cin>>z;
	}
	return 0;
}

 

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