Codeforces Round #503 (by SIS, Div. 1)第四题 the hat

原题链接:B. The hat

题意:有n(偶数)个人围成一个圈,每个人身上有一个数字,保证相邻两个人的数字差为1,

现在要把第i个人和第i+n/2个人面对面站着,例如现在有8个人,站好后如下:

1 2 1 2

3 4 3 2

第1个人和第5个人面对面,第2个人和第6个人面对面,以此类推。。。

现在的问题是你可以询问q(q<=60)次,在n(2<=n<=100000)个人中

找出一对面对面站着且数字相同的人,输出这两个人任意一个人的位置,没找到输出-1;

首先当n%4!=0的时候我们直接输出-1即可,为什么可以这样?

我们可以先看一组数据:

1 2 3

2 1 2

第一个人为奇数,那么因为保证相邻两个人的数字差为1,所以第二个人肯定为偶数。。。第一排最后一个为奇数

下面一排的第一个人跟第一排的最后一个人数字差为1,所以他肯定为偶数,于是上面一排跟下面一排奇偶性刚好错开

所以上面的数不可能等于下面的数,证完了,是不是很简单?

OK,接下来我们考虑一般情况,一共最多有50000对数,我们只可以询问

最多60次,如果从前往后直接询问肯定不行,有经验的选手容易想到二分查找,

没错,这道题还真就是二分查找,怎么查找呢,我们先看一组数据:

7 6 5 4 5 6 5 4 3 2

1 2 3 4 3 2 3 4 5 6

设上面一排为A,第i个数为Ai,下面一排为B,第i个数为Bi

A1>B1,A只有往后减少,B往后增加中间才能出现相等的情况,并且由于最后An要和B1要相差1,Bn和A1也要相差1

所以肯定是有解的。先查第一对,A1=7,B1=1,得出上下排大小关系然后在第二对和最后一对中间进行二分查找,具体实现见代码:

#include <bits/stdc++.h>
using namespace std;
int n,x,y,a,b;
int main(){
    cin>>n;
    if(n%4!=0){
        printf("! -1\n");
        return 0;
    }
    printf("? 1\n");
    cin>>x;
    printf("? %d\n",1+n/2);
    cin>>y;
    if(x==y){
        printf("! %d\n",x);
        return 0;
    }
    int l=2,r=n/2;
    while(l<=r){
        int m=(l+r)/2;
        printf("? %d\n",m);
        cin>>a;
        printf("? %d\n",m+n/2);
        cin>>b;
        if(a==b){
            printf("! %d\n",m);
            return 0;
        }
        else if(x>y&&a>b||x<y&&a<b)l=m+1;
        else r=m;
    }
}

原文地址:https://www.cnblogs.com/ccsu-kid/p/9476920.html

时间: 2024-08-01 21:19:37

Codeforces Round #503 (by SIS, Div. 1)第四题 the hat的相关文章

Codeforces Round #503 (by SIS, Div. 2)

Codeforces Round #503 (by SIS, Div. 2) https://codeforces.com/contest/1020 A 1 #include <iostream> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #include <cstdio> 6 #include <cstdlib> 7 #include <s

Codeforces Round #503 (by SIS, Div. 2) Partial Solution

从这里开始 题目列表 瞎扯 Problem A New Building for SIS Problem B Badge Problem C Elections Problem D The hat Problem E Sergey's problem 瞎扯 例行快速切A.B.C. 然后发现D是交互.E也不像是我能做的题,感觉完蛋了. 最后8分钟想出D.狂码代码,然后比赛结束后1分钟过样例. 第二天早上再花4分钟AC.我真是个大菜逼.. 于是这场cf比赛变成了真·手速场.几个friends手速比我

Codeforces Round #503 (by SIS, Div. 2) C. Elections

气死我了人生中第一次打cf就掉分了 A题大水题浪费太多时间囧明明都是A两题亮老师还上分了.. 表示C题打的时候就想到正解啊(而且还更加优秀,因为家里老爷机暴力跑的超龟以为不行 其实是没认真算复杂度),虽然不会证三分性,但是最后还是AC了,暴力1000ms+ 三分40ms+ 看着就很奇淫的题,猛然脑海里就想到二分政党的最后得到的选票,然后发现没有单调性,但好像满足三分 然后每次就贪心,for一遍把那些比1政党本来就有的选票+要多拿的选票还要多的拿到比这个值少1 假如还不够要多拿的,那就在剩下的拿最

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

cf1020D 题意: 交互题目,在有限的询问中找到一个x,使得数列中的第x位和第(x+n/2)位的值大小相同.数列保证相邻的两个差值为1或-1: 思路: 构造函数f(x) = a[x] - a[x + n/2] ,由于a数列差值为1或-1,所以可以发现f(x)是连续的.然后就可以用二分了,这种二分的check方式是自己第一次见的.就是通过f(mid)和f(d)的正负来判断区间的移动.其中d是任选的. 代码: #include <iostream> #include <cstdio>

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

有图可以直观发现,如果一开始的pair(1,1+n/2)和pair(x, x+n/2)大小关系不同 那么中间必然存在一个答案 简单总结就是大小关系不同,中间就有答案 所以就可以使用二分 #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <climits> #include <cstring> #include <s

Educational Codeforces Round 48 (Rated for Div. 2) - 赛后补题

C. Vasya And The Mushrooms 题解:拿笔画他的行走路线,你会发现可以前缀和预处理一些东西出来. const int N = 300005; int n; ll a[N], b[N], dp[2][N], sp[2][N], sum[N]; int get_a() { dp[0][0] = 0; for (int i = 1; i < n; ++i) { dp[0][i] = dp[0][i - 1] + 1ll * i * a[i]; } int t = n; dp[1]

Educational Codeforces Round 59 (Rated for Div. 2) (前四题)

A. Digits Sequence Dividing(英文速读) 练习英语速读的题,我还上来昏迷一次....只要长度大于2那么一定可以等于2那么前面大于后面就行其他no 大于2的时候分成前面1个剩下后面一定是对的因为按照数字大小 代码 #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n; cin>>n;

Educational Codeforces Round 36 (Rated for Div. 2)

Educational Codeforces Round 36 (Rated for Div. 2) F. Imbalance Value of a Tree You are given a tree T consisting of n vertices. A number is written on each vertex; the number written on vertex i is ai. Let's denote the function I(x,?y) as the differ

Educational Codeforces Round 36 (Rated for Div. 2) 题解

Educational Codeforces Round 36 (Rated for Div. 2) 题目的质量很不错(不看题解做不出来,笑 Codeforces 920C 题意 给定一个\(1\)到\(n\)组成的数组,只可以交换某些相邻的位置,问是否可以将数组调整为升序的 解题思路 首先如果每个数都能通过交换到它应该到的位置,那么就可以调整为升序的. 但实际上交换是对称的,如果应该在的位置在当前位置前方的数都交换完成,那么整体就是排好序的,因为不可能所有不在相应位置的数都在相应位置的后方.