考慮弱化版,當寫有同樣整數的卡片只有 \(1\) 張時如何做。
可以發現性質。
- \(P_{A_i}\) 最大的 \(i\) 在詢問 \((i,x)\) 時必然不返回 \(A_i\)。
- \(P_{A_i}\) 第二大的 \(i\) 在詢問 \((i,x)\) 時必然只有一種情況返回 \(A_i\)。
- \(P_{A_i}\) 最小的 \(i\) 在詢問 \((i,x)\) 時必然返回 \(A_i\)。
考慮打擂臺。動態維護 \([1,i]\) 中 \(P_{A_i}\) 最大和第二大的 \(i\),設為 \(a,b\)。當擴充套件到 \(i\) 時。
-
若 \(i\) 不是 \([1,i]\) 中 \(P_{A_i}\) 最大或第二大,則詢問 \((a,i),(b,i)\) 均返回 \(A_i\),可以確定 \(A_i\) 的值。
-
若 \(i\) 是 \([1,i]\) 中 \(P_{A_i}\) 最大或第二大,則必然有 \((a,i),(a,b)\) 均返回 \(A_a\),或者 \((b,i),(a,b)\) 均返回 \(A_b\),可以確定 \(A_a\) 或 \(A_b\) 的值。
這樣,沒有被確定的值就是當前的最大和第二大值。若卡片有 \(N\) 張,可以在 \(2N\) 次詢問內完成。
現在考慮整道題如何做。
發現上述做法唯一的問題在於,當 \(A_a=A_b\) 時,若新進 \(A_i>A_a\),此時 \((a,i),(b,i),(a,b)\) 返回的值均相等,不能確定保留哪兩個數。
為了使返回的值不均相等,可以再記錄第三大 \(c\)。此時 \(a,b,c\) 中必然有一個數不同。這樣在兩兩詢問中必然有回答不同,可以確定保留哪三個數。
卡片有 \(2N\) 張,上述做法在擴充套件到 \(i\) 時需要詢問 \((i,a),(i,b),(i,c)\) 共 \(3\) 次,總詢問數為 \(6N\)。
#include<bits/stdc++.h>
#include "Memory2_lib.h"
#define pb emplace_back
#define mp make_pair
#define pob pop_back
using namespace std;
typedef long long ll;
typedef double db;
const ll maxn=1007,ee=1e18;
ll vis[maxn][maxn],cur[4],tmp[4],ans[maxn];
vector<ll> res[maxn];
ll ask(ll x,ll y){
if(vis[x][y]!=-1) return vis[x][y];
return vis[x][y]=vis[y][x]=Flip(x,y);
}
void Solve(int T,int N){
memset(vis,-1,sizeof(vis));
for(int i=0;i<=2;i++) cur[i]=i;
for(int i=3,tar;i<2*N;i++){
cur[3]=i,tar=3;
for(int a=0,flg;a<4;a++){
flg=1;
for(int b=0,c=-1;b<4;b++)if(a!=b){
tmp[++c]=ask(cur[a],cur[b]);
if(c&&tmp[c]!=tmp[c-1]) flg=0;
}
if(flg){tar=a; break;}
}
ans[cur[tar]]=tmp[0];
for(int a=tar+1;a<4;a++) cur[a-1]=cur[a];
}
tmp[0]=ask(cur[0],cur[1]),tmp[1]=ask(cur[1],cur[2]),tmp[2]=ask(cur[0],cur[2]);
if(tmp[0]==tmp[1]) ans[cur[1]]=tmp[0],ans[cur[0]]=ans[cur[2]]=tmp[2];
else if(tmp[0]==tmp[2]) ans[cur[0]]=tmp[0],ans[cur[1]]=ans[cur[2]]=tmp[1];
else ans[cur[2]]=tmp[1],ans[cur[0]]=ans[cur[1]]=tmp[0];
for(int i=0;i<2*N;i++) res[ans[i]].pb(i);
for(int i=0;i<N;i++) Answer(res[i][0],res[i][1],i);
}