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();}
posted @ 2021-05-29 17:11  mizu164  阅读(90)  评论(0编辑  收藏  举报