目录
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
二、解题报告
1、思路分析
一个很关键的信息就是 相邻两个人拿到的数相差1
亦即相邻两个人拿到数字的奇偶性不同
如果 n 不为 4 的倍数,那么n / 2为奇数,那么 a[i] 和 a[i + n / 2] 奇偶性一定不同,我们进行特判即可
我们定义函数 f(i) = a[i] - a[i + n / 2]. g(i) = a[i] - a[i - n / 2]
我们发现如果a[i] 不等 a[i + n / 2],那么f(i) 和 g(i + n / 2)符号一定不同
而由于相邻两个人数字相差1,故 i 每变化1,其f / g值最多变化-2,0, 2,也就是说两个符号不同的值之间一定存在我们所要求的解
那么我们先提前求出f(1) 和 g(1 + n / 2),然后不断二分即可
2、复杂度
时间复杂度: O(2 logn + 2)空间复杂度:O(1)
3、代码详解
#include <bits/stdc++.h>
using i64 = long long;
using i32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
constexpr int P = 998'244'353;
int query(int x) {
std::cout << "? " << x << std::endl;
int res;
std::cin >> res;
return res;
}
void solve() {
int n;
std::cin >> n;
if (n & 2) {
std::cout << "! -1" << std::endl;
return;
}
int l = query(1), r = query(1 + n / 2);
int f = l == r ? 0 : (l < r ? 1 : -1);
if (f == 0) {
std::cout << "! " << 1 << std::endl;
return;
}
int lo = 1, hi = n / 2 + 1;
while (lo < hi) {
int x = lo + hi >> 1;
l = query(x), r = query(x + n / 2);
int nf = l == r ? 0 : (l < r ? 1 : -1);
if (nf == 0) {
std::cout << "! " << x << std::endl;
return;
}
if (nf == f)
lo = x + 1;
else
hi = x;
}
std::cout << "! " << -1 << std::endl;
}
auto FIO = []{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
int main () {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while (T --) {
solve();
}
return 0;
}