———愿天堂没人push.
为了防止暑假摆烂开学被队友嫌弃,本蒟蒻决定每天写博客汇报工作(蒟蒻的自我监督),也会写点训练题目的题解。
D. Tournament Countdown
l传送门
题意:交互题,给定2^ n个人比赛,每次可以询问2个人a,b,评测姬会返回1个值x,若x为1则a的胜场数多于b,若x为2则b的胜场数多于a,若x为0则说明a的胜场数等于b。(询问次数不能大于2^(n+1) /3上取整次)。 问最终谁赢得了比赛。
思路:容易想到设a1,a2,a3,a4,…an每次对应选2个人为一组然后淘汰1个,但是这样询问次数会超过限制,可以考虑4个人为1组,这样可以2次操作淘汰3个人。
选出a1,a2,a3,a4;
询问a1,a3,若返回值x=0,则说明a1,a3输掉了比赛,再询问a2,a4即可。
若返回值x=1(2),只需再询问a1(a2)和a4(a3)即可确定这4人组谁留了下来。询问次数累加和满足题目要求
代码:
#include <bits/stdc++.h>
#define PII pair<int,int>
#define int long long
#define PI acos(-1)
using namespace std;
const int N=2e5;
int ans[N+5],vis[N+5];
signed main()
{
//ios::sync_with_stdio(0);
//cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--){
int n;cin>>n;
vector<int> vec[2];
int op=0;
for(int i=1;i<=(1<<n);++i){
vec[op].push_back(i);
}
while(vec[op].size()>=2){
for(int i=0;i<vec[op].size();i+=2){
if(i==vec[op].size()-2){
cout<<"? "<<vec[op][i]<<" "<<vec[op][i+1]<<endl;
int x;cin>>x;
if(x==1){
vec[op^1].push_back(vec[op][i]);
}
else{
vec[op^1].push_back(vec[op][i+1]);
}
}
else{
cout<<"? "<<vec[op][i]<<" "<<vec[op][i+2]<<endl;
int x;cin>>x;
if(x==0){
cout<<"? "<<vec[op][i+1]<<" "<<vec[op][i+3]<<endl;
cin>>x;
if(x==1){
vec[op^1].push_back(vec[op][i+1]);
}
else{
vec[op^1].push_back(vec[op][i+3]);
}
}
else if(x==1){
cout<<"? "<<vec[op][i]<<" "<<vec[op][i+3]<<endl;
cin>>x;
if(x==1){
vec[op^1].push_back(vec[op][i]);
}
else{
vec[op^1].push_back(vec[op][i+3]);
}
}
else{
cout<<"? "<<vec[op][i+1]<<" "<<vec[op][i+2]<<endl;
cin>>x;
if(x==1){
vec[op^1].push_back(vec[op][i+1]);
}
else{
vec[op^1].push_back(vec[op][i+2]);
}
}
i+=2;
}
}
vec[op].clear();
op^=1;
}
cout<<"! "<<vec[op][0]<<endl;
}
return 0;
}
/*
*/