Pjudge #21651. 【PR #4】猜猜看
感觉上挺高妙一道题。
首先我们来考虑\(n=4\)怎么做,显然是进行\(4\)次询问\(2\),然后会出现两种取值,在两个较小取值都出现的点就是两个较小的点,在两个较大的取值都出现的点就是两个较大的点。然后再用两次\(1\)操作区分出较小中较大的和较大中较小的。
这启发我们利用最小的两个和最大的两个以及较小值\(L\),较大值\(R\)确定每个数的取值,我们先用\(n=4\)做出这个答案,然后每次单独加点,先取较小的和较大的询问得到一个答案\(p\),然后分类讨论:
若\(L\leq p\leq R\),则当前询问的值为\(p\)。
若\(p\leq L\),则再询问一次即可分出要被淘汰的那个。\(p\geq R\)同理。最后用\(1\)操作分出答案即可。
code:
#include "guess.h"
#include<bits/stdc++.h>
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=1e6+5,M=N*25+5,K=2e3+5,mod=1e9+7,Mod=mod-1;const db eps=1e-5;const int INF=1e9+7;
int p1,p2,p3,p4,a1,a2,a3,a4,L,R;vector<int> Ans;
vector<int> solve(int n, int m) {
int i;for(i=0;i<n;i++) Ans.PB(0);a1=query2(1,2,3);a2=query2(0,2,3);a3=query2(0,1,3);a4=query2(0,1,2);
L=min(min(a1,a2),max(a3,a4));R=max(max(a1,a2),max(a3,a4));
if(a1==L&&a2==L) p3=0,p4=1,p1=2,p2=3;if(a1==L&&a3==L) p3=0,p4=2,p1=1,p2=3;if(a1==L&&a4==L) p3=0,p4=3,p1=1,p2=2;
if(a2==L&&a3==L) p3=1,p4=2,p1=0,p2=3;if(a2==L&&a4==L) p3=1,p4=3,p1=0,p2=2;if(a3==L&&a4==L) p3=2,p4=3,p1=0,p2=1;
for(i=4;i<n;i++) {
a1=query2(p1,p3,i);if(a1>L&&a1<R) {Ans[i]=a1;continue;}
if(a1<=L) {
a2=query2(p2,p3,i);if(a1==L) Ans[p1]=L,p1=i,L=a2;else Ans[p2]=L,p2=i,L=a1;
}else{
a2=query2(p1,p4,i);if(a1==R) Ans[p3]=R,p3=i,R=a2;else Ans[p4]=R,p4=i,R=a1;
}
}if(query1(p1,p2)) Ans[p1]=1,Ans[p2]=2;else Ans[p2]=1,Ans[p1]=2;
if(query1(p3,p4)) Ans[p3]=n-1,Ans[p4]=n;else Ans[p3]=n,Ans[p4]=n-1;return Ans;
}