CodeForces - 1698D Fixed Point Guessing
CodeForces - 1698D Fixed Point Guessing
题解:二分+交互题
题目给出询问次数为15次,而\(3<=n<10^4\),很明显是二分
题目想要我们找出在数组长度n为奇数的情况下,交换\(\frac{n-1}{2}\)对互不干扰的元素,让我们找出哪一个元素没有被交换
直接看样例
4 2 5 1 3
第一次我们二分区间得到\([1,2]和[3,5]\),当我们询问\([1,2]\)区间时,系统回答:2 4,我们发现4并不属于[1,2]区间,所以2肯定是答案,我们来分析一下:[1,2]区间长度为偶数,而区间内只有奇数个不是本区间的数,说明剩下的是本区间的数的数量也是奇数个,我们知道交换是两两交换,如果现在区间是[1,4],系统给出里面元素为1 2 3 4
这说明这个区间里面肯定有两对交换了,所以答案一定是5,所以如果剩下的是本区间的数的数量为偶数,代表答案不在这个区间内,如果是奇数,说明答案一定在这个区间内
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define all(x) (x).begin(), (x).end()
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e4 + 10;
int n;
int l, r;
bool check(int mid)
{
int cnt = 0;
cout << "? " << l << " " << mid << endl;
for (int i=l;i<=mid;++i)
{
int x;
cin >> x;
if (x>=l && x<=mid)
cnt++;
}
if (cnt&1)
return 1;
else
return 0;
}
int main(void)
{
Zeoy;
int t = 1;
cin >> t;
while (t--)
{
cin >> n;
l = 1, r = n;
while (l <= r)
{
int mid = l + r >> 1;
if (check(mid))
r = mid - 1;
else
l = mid + 1;
}
cout << "! " <<l << endl;
}
return 0;
}