Codeforces Round #503 (by SIS, Div. 2)-D. The hat

版权声明:本文为博主原创文章,欢迎转载。 https://blog.csdn.net/Smiler_/article/details/82107958

D. The hat

http://codeforces.com/contest/1020/problem/D

题意:有n个人围在一起形成一个圈,当x>=1&&x<n/2时,x与(x+ n/2)坐在对面,每个人手里有一张牌,每个牌上面有一个数字,相邻两个人手中的牌上面的数字大小相差为1(+1,-1),现在问你有没有一个手中的牌与他对面人手中的牌相同,如果有输出这个人的编号,如果没有输出-1.这是一个交互题,你可以通过?x来询问x位置上人手中的数字。

思路:我们构造一个函数g[x]=f[x]-f[x+n/2],f[x]代表x位置的人手中的数字大小,由题意可知,我们的目标就是寻找一个x,使得g[x]=0,我们可以知道g[x+n/2]=-g[x],由于相邻两个数字之间差值为1,所以g[x]-g[x+1]={2,0,-2},我们可以使用二分来寻找答案,l=1,r=n/2,mid=(l+r)/2,观察g[mid]与g[1]数值符号的关系,来改变二分的区间的大小。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>


using namespace std;
const  int maxn=100050;
int f[maxn];
int n;
int Sc(int x)
{
    if(x>n/2) x=x-n/2;
    printf("? %d\n",x);
    fflush(stdout);
    int l;
    scanf("%d",&l);
    printf("? %d\n",x+n/2);
    fflush(stdout);
    int r;
    scanf("%d",&r);
    return r-l;
}
int main()
{
    scanf("%d",&n);
    f[1]=Sc(1);
    if(f[1]==0)
    {
        printf("! %d\n",1);
        fflush(stdout);
        return 0;
    }
    int l=1,r=n/2;
    while(l<=r)
    {
        int mid=(l+r)/2;
        f[mid]=Sc(mid);
        if(f[mid]==0)
        {
            printf("! %d\n",mid);
            fflush(stdout);
            return 0;
        }
        if(f[1]<0)
        {
            if(f[mid]<0) l=mid+1;
            else r=mid-1;
        }
        else if(f[1]>0)
        {
            if(f[mid]<0) r=mid-1;
            else l=mid+1;
        }
    }
    printf("! %d\n",-1);
    fflush(stdout);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Smiler_/article/details/82107958