zoukankan      html  css  js  c++  java
  • CodeForces 1363D. Guess The Maximums

    题意:通过查询构造出答案要求的密码,每次查询可以询问数组A中指定的集合的最大值,最多可以查询12次,我们要构造的密码序列,对于一个密码Pi, Pi为除了Si这个集合中索引对应的数组A中的数字的最大值,Si是k个互不独立的集合。

    分析:题目中说Si是k个互不独立的集合,也就是最大值的下标最多出现在一个集合中,所以密码串P中最多一个数字是和最大值不同的,其它都是最大值,所以我们先询问整个数组中的最大值,然后二分查找这个最大值所在的下标,查找的时候,我们查找包含最大值的区间,每次查找的时候,查找前缀和包含最大值的区间,不包含的时候,查找区间的最大值就会小于我们所要的答案,具有单调性。然后我们再遍历一下每个密码对应的集合,查看是不是包含最大值,如果有的话,我们最多询问一次集合,就可以查出最大值。总共次数为1 + log(1000) + 1 = 12次。

    对于这个查询的过程,我们可以单独写成一个函数query。对于每次的查询,它都会输出这个查询区间的最大值,等待我们输入。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <algorithm>
    
    using namespace std;
    const int N = 1005;
    vector<int> v[N];
    int res[N];
    
    //写成一个函数查询
    int query(int x)
    {
    	printf("? ");
    	//查询的集合大小
    	printf("%d ", x);
    	for (int i = 1; i <= x; ++i)
    	{
    		printf("%d ", i);
    	}
    	printf("
    ");
    	fflush(stdout);
    	//读入查询的区间内的最大值,并返回
    	int res;
    	scanf("%d", &res);
    	return res;
    }
    
    int main()
    {
    	int t;
    	scanf("%d", &t);
    
    	while (t--)
    	{
    		//数组a的大小,集合的数量
    		int n, k;
    		scanf("%d%d", &n, &k);
    
    		for (int i = 1; i <= k; ++i)
    		{
    			v[i].clear();
    			int sz;//集合的大小
    			scanf("%d", &sz);
    			int u;
    			for (int j = 1; j <= sz; ++j)
    			{
    				scanf("%d", &u);
    				v[i].push_back(u);
    			}
    		}
    
    		//查询整个数组a的最大值
    		int mx = query(n);
    
    		//查询mx所在的下标
    		int l = 1, r = n;
    
    		int pos = 1;
    		while (l < r) {
    			int mid = l + r >> 1;
    			if (query(mid) == mx) {
    				r = mid;
    			}
    			else {
    				l = mid + 1;
    			}
    		}
    
    		pos = l;
    
    		//最多一个位置的数不是mx
    		for (int i = 1; i <= k; ++i)
    		{
    			bool flag = false;
    			map<int, int> mp;
    
    			for (int j = 0; j < v[i].size(); ++j)
    			{
    				if (v[i][j] == pos)
    				{
    					//不包含最大值
    					flag = true;
    				}
    				mp[v[i][j]] = 1;//这个位置是不行的
    			}
    			if (!flag)
    			{
    				res[i] = mx;
    			}
    			else
    			{
    				printf("? ");
    				printf("%d ", n - v[i].size());
    				for (int i = 1; i <= n; ++i)
    				{
    					if (mp[i]) continue;
    					printf("%d ", i);
    				}
    				printf("
    ");
    				fflush(stdout);
    				int p = 0;
    				scanf("%d", &p);
    				res[i] = p;
    			}
    		}
    
    		printf("! ");
    		for (int i = 1; i <= k; ++i)
    		{
    			printf("%d ", res[i]);
    		}
    		printf("
    ");
    
    		fflush(stdout);
    		char tmp[100];
    		scanf("%s", tmp);
    	}
    
    
    	return 0;
    }
    
  • 相关阅读:
    二分查找 java代码
    Failed at the bitcore-node@3.1.3 preinstall script './scripts/download' 设置linux proxy (代理)的方式
    github命令行实用操作
    H5无障碍旁白模式使用网页支持
    Vue框架搭建入门到熟悉
    解决IOS下返回不刷新的问题
    小程序—跳转 数据传递
    微信小程序——地图
    常用的正则判断
    JS 控制输入框输入表情emoji 显示在页面上
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13034359.html
Copyright © 2011-2022 走看看