Codeforces Round #770 (Div. 2)D

传送门
题目大意:
交互题, n ( 4 ≤ n ≤ 1000 ) n(4\leq n\leq1000) n(4n1000)个数字组成的数列 a 1 , a 2 , … , a n ( 0 ≤ a i ≤ 1 0 9 ) a_{1},a_{2},…,a_{n}(0\leq a_{i}\leq10^9) a1,a2,,an(0ai109),有且仅有 1 1 1 0 0 0,每次询问 i , j , k i,j,k i,j,k,会给出 m a x ( a i , a j , a k ) − m i n ( a i , a j , a k ) max(a_{i},a{j},a{k})-min(a_{i},a_{j},a_{k}) max(ai,aj,ak)min(ai,aj,ak)的值,最多询问 2 n − 2 2n-2 2n2次,最后需要输出 i , j i,j i,j,使 a i , a j a_{i},a_{j} ai,aj当中有一个为 0 0 0

思路:
题目可以转化为找出 n − 2 n-2 n2个绝对不会为 0 0 0的位置。我们考虑 4 4 4个数字 0 , a , b , c 0,a,b,c 0,a,b,c,不妨设 0 < a ≤ b ≤ c 0<a\leq b\leq c 0<abc,那么在 4 4 4个数当中,我们记不选数字 a a a而选择了其他 3 3 3个数字询问而得到的答案记为 a ′ a' a,那么上面的例子中, 0 ′ = c − a , a ′ = c , b ′ = c , c ′ = b 0'=c-a,a'=c,b'=c,c'=b 0=ca,a=c,b=c,c=b,这 4 4 4 a n s ans ans中最大的两个值所对应的位置一定不会为 0 0 0,因为如果为 0 0 0,那么舍弃掉既不是 0 0 0也不是这 4 4 4个当中最大值的两个位置中的一个去询问会得到的回答是这 4 4 4个数当中的最大值,一定比舍弃掉 0 0 0的询问更大,所以我们可以把 4 4 4 a n s ans ans中最大的两个位置去掉,这样通过每轮 4 4 4个询问我们可以排除掉两个位置,( 4 4 4位置都没有 0 0 0的情况下也可以这样算,都不是 0 0 0去掉两个显然没有问题)当 n n n为偶数时,我们只需要询问 n − 2 2 ∗ 4 = 2 n − 4 \frac{n-2}{2}*4=2n-4 2n24=2n4次,而如果为奇数,最后会剩余 3 3 3个没有去掉的位置,我们只需要把之前任意一个去掉过的位置拿过来凑够 4 4 4个再进行 1 1 1轮即可,总的询问次数时 n − 3 2 ∗ 4 + 4 = 2 n − 2 \frac{n-3}{2}*4+4=2n-2 2n34+4=2n2,都可以满足要求。

代码:

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
//#define int LL
//#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#pragma warning(disable :4996)
const double eps = 1e-8;
const LL mod = 1000000007;
const LL MOD = 998244353;
const int maxn = 1010;

int T, N;
bool used[maxn];

void solve()
{
	PII res[4];
	vector<int>num;
	int lst = N, pos = 1, tmp, ans;
	while (lst > 3)
	{
		while (num.size() < 4)
		{
			if (!used[pos])
				num.push_back(pos);
			pos++;
		}
		for (int i = 0; i < 4; i++)
		{
			cout << "? " << num[i] << ' ' << num[(i + 1) % 4] << ' ' << num[(i + 2) % 4] << endl;
			cin >> ans;
			res[i] = PII(ans, num[(i + 3) % 4]);
		}
		sort(res, res + 4);
		int a = res[2].second, b = res[3].second;
		used[a] = used[b] = true;
		num.erase(find(num.begin(), num.end(), a)), num.erase(find(num.begin(), num.end(), b));
		tmp = a;
		lst -= 2;
	}
	if (lst == 2)
		cout << "! " << num[0] << ' ' << num[1] << endl;
	else
	{
		while (num.size() < 3)
		{
			if (!used[pos])
				num.push_back(pos);
			pos++;
		}
		num.push_back(tmp);
		for (int i = 0; i < 4; i++)
		{
			cout << "? " << num[i] << ' ' << num[(i + 1) % 4] << ' ' << num[(i + 2) % 4] << endl;
			cin >> ans;
			res[i] = PII(ans, num[(i + 3) % 4]);
		}
		sort(res, res + 4);
		int a = res[2].second, b = res[3].second;
		used[a] = used[b] = true;
		num.erase(find(num.begin(), num.end(), a)), num.erase(find(num.begin(), num.end(), b));
		cout << "! " << num[0] << ' ' << num[1] << endl;
	}
}

int main()
{
	IOS;
	cin >> T;
	while (T--)
	{
		cin >> N;
		memset(used, false, sizeof(used));
		solve();
	}

	return 0;
}
posted @ 2022-03-02 20:07  Prgl  阅读(31)  评论(0)    收藏  举报