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;
}
posted @ 2023-01-08 14:09  Zeoy_kkk  阅读(22)  评论(0编辑  收藏  举报