1407C-Chocolate Bunny
Description
Analysis
题目概述
交互题
给出一个 1 → n 1\to n 1→n 的排列( 1 ≤ n ≤ 1 0 4 1\le n\le10^4 1≤n≤104),最多可以询问 2 n 2n 2n 次,对于每个询问 x , y x,y x,y,给出 a x m o d a y a_x\space mod\space a_y ax mod ay 的值,求原排列
分析
对于任何一组询问 x , y x,y x,y, a x , a y a_x,a_y ax,ay 必然存在大小关系,设 a x < a y a_x<a_y ax<ay
则对于询问 x , y x,y x,y, a x m o d a y = a x a_x\space mod\space a_y=a_x ax mod ay=ax
对于询问 y , x y,x y,x, ( a y m o d a x ) < a x < a y (a_y\space mod\space a_x)<a_x<a_y (ay mod ax)<ax<ay
通过两次询问,一定能确定 a x , a y a_x,a_y ax,ay 中的最小者
与此同时,排列中的最大数 n n n 是无法通过模运算直接得出的
-
由上述结论,通过构造 2 ( n − 1 ) 2(n-1) 2(n−1) 次询问,即可直接确定整个序列中 n − 1 n-1 n−1 个较小的数
则剩余的最后一个数一定为 n n n
-
考虑如何构造 2 ( n − 1 ) 2(n-1) 2(n−1) 次询问:
对于每一组询问 x , y x,y x,y 和 y , x y,x y,x,较小者一定确定,较大者一定不确定
因此,可以考虑维护一组询问中较大者的位置,不断将其与后续的数进行询问,并维护该最大值(该过程可顺次遍历实现,思想类似于递归?),则经过 2 ( n − 1 ) 2(n-1) 2(n−1) 次询问后,所记录的位置即 n n n 的位置
Code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
constexpr const int N = 1e4 + 10;
int a[N], n, a1, a2, tmax, cnt;
inline void ask(int l, int r)
{
cout << "? " << l << " " << r << endl;
}
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
cin >> n;
int cur = 1;
for(int i = 2; i <= n; i++)
{
ask(cur, i);
cin >> a1;
ask(i, cur);
cin >> a2;
if(a1 > a2)
{
a[cur] = a1;
cur = i;
}else
a[i] = a2;
}
a[cur] = n;
cout <<"! ";
for(int i = 1; i <= n; i++)
cout << a[i] << " ";
return 0;
}
Tag
交互、全局维护、模运算