Codeforces Round #503 (by SIS, Div. 2) D. The hat(交互题)

题目链接:http://codeforces.com/contest/1020/problem/D题意描述:这是一个交互题,互交题就是你要输出一些问题,评测机就会回答你一些问题你要在规定的提问次数中找到问题答案并回答后return 0;这个题目是给出一个偶数n(n<=1e5),n个人编号1到n坐一圈,编号i的对面是编号i+n/2的人(i<=n/2),反过来也是一样每...
摘要由CSDN通过智能技术生成

题目链接:http://codeforces.com/contest/1020/problem/D

题意描述:

这是一个交互题,互交题就是你要输出一些问题,评测机就会回答你一些问题

你要在规定的提问次数中找到问题答案并回答后return 0;

这个题目是给出一个偶数n(n<=1e5),n个人编号1到n坐一圈,编号i的对面是编号i+n/2的人(i<=n/2),反过来也是一样

每个人手上有一个数字ai(ai<=1e9),规则是任意相邻两个人的数字之差为1或-1,1和n也满足这个限制

现在你有询问方式《? x》,机器会回答你x编号的人手上的数字。

你的任务是找到任意一个人跟其对面人手上数字相同,并回答《! ans》,ans为满足条件的人

如果没有这样的人,回答《! -1》

题目分析:

考虑n=4k+2的情况,每个人跟其对面的人之间相差2k+1个人,因为任意相邻两个人的数字之差为1或-1,而且2k+1为奇数,那么对面的人跟他经过奇数次+1或-1之后现在不可能是跟他相同数字,所以n=4k+2的情况一定无解。

考虑n=4k的情况,每个人跟其对面的人之间相差2k个人,同上,可能会有解,实际上是必定有解:

图中a[i]表示每个人拥有的数字,d[i]表示第i个人的数字跟对面的人数字之差,

可以发现d[i]和d[i+1]之间的差值只能是+2 -2或0,并且对面两个人之间的d[i]值是相反数,d[i]一定是偶数

题目要求的答案就是di=0的这些点,设位置l和位置r初始相对,由上可知d[l] = -d[r]

那么显然在任意两个异号的d[l]和d[r]之间必定存在d[ans]的值为0,二分即可找到ans,且ans必定存在。

AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,ans[3];
inline int across(int o){    //找到位置o的对面的位置id
    return (o+n/2-1)%n+1;    //-1取模再+1,结果范围在1到n
}
inline int query(int o){
    printf("? %d\n? %d\n",o,across(o));
    fflush(stdout);
    scanf("%d%d",&ans[1],&ans[2]);
    if(ans[1] == ans[2]){   //询问到答案,输出并退出程序
        printf("! %d\n",o);
        fflush(stdout);
        exit(0);
    }
    return ans[1]>ans[2]?1:-1;
}
int main(){
    scanf("%d",&n);
    if(n%4){            //n不是4的倍数无解
        printf("! -1\n");
        fflush(stdout);
        return 0;
    }
    int T=30,l=1,r=1+n/2,mid,dl,dr,dm;
    dl=query(l);dr=-dl;
    while(l+1<r){
        mid=(l+r)>>1;
        dm=query(mid);
        if(dl<0){
            if(dm<0)l=mid;  //dm与dl同号则更新l
            else r=mid;
        }else if(dr<0){
            if(dm<0)r=mid;  //dm与dr同号则更新r
            else l=mid;
        }
    }
    query(r);
    query(l);
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值