Codeforces Round #812 (Div. 2) D. Tournament Countdown(交互题)
记录一下第一次写交互题
题目大意:一共有1<<n个人参加一场竞标赛,需要你通过比较两人的胜场来判断谁晋级,最终获得第一名
最多1/3*2^(n+1)次询问,每次询问query(a,b),如果a胜场多返回1,如果b胜场多返回2,相同胜场返回0
找到冠军后输出“! i”(i为冠军的编号)
思路:
每次取四个人一组,因为如果这一组人进行了t轮比赛后,最终有一人胜出,那么他们的胜场将为
[ t , t , t+1 , t+2 ],而且 t 和 t 不能出现在同一组,那么他们的胜场排列基本如下[ t , t+1 t , t+2 ]
所以先对奇数进行查询(query(a[i],a[i+2])),如果相同(t==0),说明他们俩同时被淘汰,此时只用比较偶数组,谁多谁胜出
否则如果不同,若返回1,说明a[i]为t+1或者t+2,这时只用比较a[i]与a[i+3]即可
同理返回2
1 # include<iostream>
2 # include<bits/stdc++.h>
3 using namespace std;
4 # define int long long
5
6 int ask(int a, int b) {
7 cout << "? " << a << ' ' << b << endl;
8 int t;
9 cin >> t;
10 return t;
11 }
12 int tt;
13 signed main() {
14 ios::sync_with_stdio(0);
15 cin.tie(0);
16 cout.tie(0);
17 cin >> tt;
18 while (tt--) {
19 int n;
20 cin >> n;
21 vector<int> a;
22 n = 1 << n;
23 for (int i = 1; i <= n; ++i) {
24 a.push_back(i);
25 }
26 while (n >= 4) {
27 vector<int> b;
28 for (int i = 0; i < n; i += 4) {
29 int t = ask(a[i], a[i + 2]);
30 if (t == 0) {
31 int t2 = ask(a[i + 1], a[i + 3]);
32 if (t2 == 1) b.push_back(a[i + 1]);
33 else b.push_back(a[i + 3]);
34 } else if (t == 1) {
35 int t2 = ask(a[i], a[i + 3]);
36 if (t2 == 1) b.push_back(a[i]);
37 else b.push_back(a[i + 3]);
38 } else {
39 int t2 = ask(a[i + 1], a[i + 2]);
40 if (t2 == 1) b.push_back(a[i + 1]);
41 else b.push_back(a[i + 2]);
42 }
43 }
44 n /= 4;
45 a.swap(b);
46 }
47 if (a.size() == 2) {
48 int t = ask(a[0], a[1]);
49 if (t == 1) cout << '!' << ' ' << a[0] << endl;
50 else cout << '!' << ' ' << a[1] << endl;
51 } else cout << '!' << ' ' << a[0] << endl;
52
53 }
54
55
56 return 0;
57 }