zoukankan      html  css  js  c++  java
  • CF1526F Median Queries【交互】

    这是一道交互题

    给定正整数 (n),交互库有长为 (n) 的排列 (p),你至多可以询问 (2n+420) 次三个不同正整数 (a,b,c),交互库告诉你 ({|p_a-p_b|,|p_b-p_c|,|p_c-p_a|}) 的中位数。(T) 组数据。

    (nge 20)(sum nle 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
    ", 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
    ", 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('
    ');
    	fflush(stdout);
    	read(n);
    }
    int main(){read(T); while(T --) solve();}
    
  • 相关阅读:
    6 网络爬虫引发的问题及Robots协议
    WEB测试方法总结-笔记(转)
    最全的Http协议、get和post请求的整理
    random()函数的应用---面试
    求两个列表的交集、差集、并集---面试
    python中函数参数传递--引用传递(面试)
    linux重定向命令>和>>---面试
    正则表达式re.findall和re.search的使用---面试
    关于可迭代对象的详解
    sorted()函数排序的灵活运用---面试
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/14825750.html
Copyright © 2011-2022 走看看