CF1019B The hat

一、题目

点此看题
在这里插入图片描述
谢谢恩泽的题面翻译,@Arextre

二、解法

首先 n n 2 2 的倍数但不为 4 4 的倍数肯定是不行的,因为相对两个数隔了偶数个,所以奇偶性一定不同,所以两个数不同,可以在一开始的时候判掉。

i i' i i 的对应点, t i = a i a i t_i=a_i-a_{i'} ,有一个性质,就是 t i + 1 t i = ± 2   o r   0 t_{i+1}-t_i=\pm2\space or\space0 ,证明很简单,就是 t i + 1 t_{i+1} t i t_i 的差异只有两个格子的增减,所以只有这些情况。

可以考虑二分,设 l = 1 , r = n 2 l=1,r=\frac{n}{2} l , r l,r 算出来的 t t 一开始就异号,所以里面一定有解,我们假设分到 m i d mid ,判断 m i d mid 算出来的 t t t l tl 还是 t r tr 异号,向那边继续分即可,中间算 t t 的时候就判断一下有没有算出 0 0 ,算出 0 0 了就找到答案了。

讲完这个解法,相信你还有一些问题,比如为什么 l , r l,r 一开始就异号,我们把 t t 看作一个连续的函数,现在这段函数的定义域是 [ 1 , 2 n ] [1,\frac{2}{n}] ,发现 t n 2 + 1 t_{\frac{n}{2}+1} t n 2 t_{\frac{n}{2}} 差值一定是 ± 2   o r   0 \pm2\space or\space0 ,所以可以把定义域扩展到 [ 1 , n 2 + 1 ] [1,\frac{n}{2}+1] 然后 1 1 n 2 + 1 \frac{n}{2}+1 一定异号(你看定义呀!),所以 l , r l,r 一开始就异号。

真是道神题,贴个代码吧qwq。

#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
int read()
{
 int x=0,flag=1;char c;
 while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
 while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
 return x*flag;
}
int n;
int ask(int x)
{
    cout<<"? "<<x<<endl;int a=read();
    cout<<"? "<<x+n/2<<endl;int b=read();
    if(a==b)
    {
        cout<<"! "<<x<<endl;
        exit(0);
    }
    return a-b;
}
int main()
{
    n=read();
    if(n%4) {printf("! -1\n");return 0;}
    int l=1,r=n>>1,tl=ask(l),tr=ask(r);
    while(l<=r)
    {
        int mid=(l+r)>>1,tm=ask(mid);
        if(tl*tm<0) r=mid-1,tr=tm;
        else l=mid+1,tl=tm;
    }
    cout<<"! -1"<<endl;
}
发布了257 篇原创文章 · 获赞 13 · 访问量 6726

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/104180167