D - Guess The Maximums(交互题)

理解:假设n=7,k=3,A=[1 5 3 7 2 6 4],按照题意将A划分为3个集合,s1=[1,4],s2=[2,5],s3=[3,6,7]。其中s1,s2,s3是所划分集合中元素的下标,对应的w1=[A[1]=1,A[4]=7],w2=[5,2],w3=[3,6,4]。
求解:答案总共有为k个数字,从p1到pk,对于每个pi,当前的值是A[]中删去当前集合中所有下标所对应的值后的全局最大值。这里可以发现,如果A[]最大值MX不在当前的划分,那么当前的pi就是MX,否则就要模拟一次求解。所有,用1次查询找到MX,用<=10次的查询找到MX的下标,对于仅有的当前划分包含MX的,再用1次查询,可在<=12查询中求得正确解。

int t;
vector<int> G[1005];
int query(int x)
{
	int ans;
	printf("? %d ", x);
	f(i, 1, x)printf("%d ", i);
	cout << endl;
	scanf("%d", &ans);
	return ans;
}
void wo()
{
	vector<int> res;
	f(i, 1, 1004)G[i].clear();
	int n, k, x, y;
	scanf("%d%d", &n, &k);
	f(i, 1, k) {
		scanf("%d", &x);
		f(j, 1, x)
			scanf("%d", &y), G[i].emplace_back(y);
	}
	int mx = query(n);//1次
	//二分查询区间最大值,找到最大值所在集合
	int l = 1, r = n;
	int idx=-1;
	while (l <= r)//2^10=10次
	{
		int mid = (l + r) / 2;
		if (query(mid) == mx)
		{
			idx = mid;
			r = mid - 1;
		}
		else l = mid + 1;
	}
	f(i, 1, k)
	{
		bool fg = false;
		for (auto I : G[i])
		{
			if (I == idx) { fg = true;break; }
		}
		if (fg)	//最大值在当前集合,再找一次
		{
			int tmp;
			set<int> st;
			f(j, 1, n)st.insert(j);
			for (auto I : G[i])st.erase(I);
			printf("? %d ",st.size());
			for (auto I : st)printf("%d ", I);
			cout << endl;
			scanf("%d", &tmp);
			res.emplace_back(tmp);
		}
		else res.emplace_back(mx);
	}
	printf("! ");
	for (auto I : res)printf("%d ", I);
	cout << endl;
}
int main()
{
	cin >> t;
	while (t--)
	{
		wo();
		string op;
		cin >> op;
		if (op == "Correct")continue;
		else break;
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值