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),反過來也是一樣

每個人手上有一個數字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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章