シンプルな設定で良かったです。
https://yukicoder.me/problems/no/850
問題
N人の人がいて、1~N位の順位が付いた。
ある2人の順位を問い合わせたとき、どちらの順位が上か答えてくれるクエリがある。
このクエリを334回まで用いて、2位の人を特定せよ。
解法
1位を特定しようとすると、(N-1)回問い合わせが必須である。
Nの上限が300なので、残り35回以下で2位を特定することを考える。
2位は1位以外に負けないので、言い換えればどこかで敗者がいると、1位の人に負けた人の中に2位の人がいる。
そこで、まずN名で2分木型のトーナメントを組ませ1位を特定する。
その際、各人が誰に負けたかを覚えておこう。
トーナメントを終え1位が確定すると、1位に負けた人はlogN人しかいないはずなので、その中での最上位の人を探せばよい。
int N; int lose[333]; int ask(int x,int y) { int r; cout<<"? "<<x<<" "<<y<<endl; cin>>r; return r; } int ans(int a) { cout<<"! "<<a<<endl; exit(0); } int win(int L,int R) { if(L+1>=R) return L; int M=(L+R)/2; int x=win(L,M); int y=win(M,R); if(ask(x,y)==x) { lose[y]=x; return x; } else { lose[x]=y; return y; } } void solve() { int i,j,k,l,r,x,y; string s; cin>>N; x=win(1,N+1); vector<int> V; for(i=1;i<=N;i++) if(lose[i]==x) V.push_back(i); int cur=V[0]; for(i=1;i<V.size();i++) cur=ask(cur,V[i]); ans(cur); }
まとめ
クエリ上限が400とか言われたら却って迷ったかも。