CF1526F Median Queries【交互】
这是一道交互题
给定正整数 \(n\),交互库有长为 \(n\) 的排列 \(p\),你至多可以询问 \(2n+420\) 次三个不同正整数 \(a,b,c\),交互库告诉你 \(\{|p_a-p_b|,|p_b-p_c|,|p_c-p_a|\}\) 的中位数。\(T\) 组数据。
\(n\ge 20\),\(\sum n\le 10^5\),\(p_1<p_2\),non-adaptive。
看到这个魔怔限制就知道肯定是二合一(分步做)
首先可以不管值的对称性,只要先做一个答案然后 \(p_1>p_2\) 的时候令 \(p_i:=n+1-p_i\) 即可。
知道了 \(1,2\) 的位置之后遍历一遍就做完了。
知道了 \(|p_a-p_b|\le (n-4)/3\) 的 \(a,b\) 之后遍历一遍就找到了 \(1,2\) 的位置。
暴力随一些 \(a,b,c\) 直到交互库返回值 \(\le (n-4)/6\) 即可。
#include<bits/stdc++.h>
#define PB emplace_back
using namespace std;
const int N = 100003;
template<typename T>
void read(T &x){
int ch = getchar(); x = 0;
for(;ch < '0' || ch > '9';ch = getchar());
for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
}
template<typename T>
bool chmax(T &a, const T &b){if(a < b) return a = b, 1; return 0;}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int T, n, m, a, b, p[N], mx;
vector<int> E[N];
#ifdef NTFOrz
int ans[N];
#endif
int ask(int x, int y, int z){
printf("? %d %d %d\n", x, y, z);
#ifdef NTFOrz
int a[3] = {abs(ans[x] - ans[y]), abs(ans[y] - ans[z]), abs(ans[z] - ans[x])};
sort(a, a + 3); printf("%d\n", a[1]); return a[1];
#else
fflush(stdout);
int _; read(_); return _;
#endif
}
void solve(){
read(n); m = (n-4)/6; mx = 0;
#ifdef NTFOrz
for(int i = 1;i <= n;++ i) read(ans[i]);
#endif
for(int i = 0;i < n;++ i) E[i].resize(0);
while(true){
int c = rng() % n + 1;
a = rng() % n + 1;
b = rng() % n + 1;
if(a != b && b != c && c != a && ask(a, b, c) <= m) break;
}
for(int i = 1;i <= n;++ i)
if(i != a && i != b){
int v = ask(i, a, b);
chmax(mx, v); E[v].PB(i);
}
if(E[mx-1].size() > 1 && ask(E[mx-1][0], E[mx][0], a) > ask(E[mx-1][1], E[mx][0], a))
swap(E[mx-1][0], E[mx-1][1]);
p[a = E[mx][0]] = 1;
p[b = E[mx-1][0]] = 2;
for(int i = 1;i <= n;++ i)
if(i != a && i != b)
p[i] = ask(i, a, b) + 2;
if(p[1] > p[2])
for(int i = 1;i <= n;++ i)
p[i] = n + 1 - p[i];
putchar('!');
for(int i = 1;i <= n;++ i){
printf(" %d", p[i]);
#ifdef NTFOrz
assert(p[i] == ans[i]);
#endif
}
putchar('\n');
fflush(stdout);
read(n);
}
int main(){read(T); while(T --) solve();}