1. 程式人生 > >【互動題】Codeforces 1019B The hat

【互動題】Codeforces 1019B The hat

分析:

非常簡單的互動題,二分答案的左端點位置(在[1,n/2]中)
由於每兩個相鄰的點值都相差1,所以可以把詢問的值看作一個由-1或1組成的序列的字首和。
答案就是要求兩個字首和相差為0,長度為n/2的區間。

所以二分的時候,如果當前區間的左端點值(即a[l+n/2]-a[l])與中間的值(a[mid+n/2]-a[mid])同號,則如果有答案,右端點的值(a[r+n/2]-a[r])一定與中間的值(a[mid+n/2]-a[mid])異號,每次忘異號的那個區間找即可。(因為異號的區間一定經過了0這個點)

#include<cstdio>
#include<cstring>
#include<algorithm> #include<cmath> #include<vector> #define SF scanf #define PF printf #define MAXN 100010 using namespace std; typedef long long ll; int n,m,p,v,l,r; int a[MAXN]; bool used[MAXN]; int ask(int x){ if(used[x]) return a[x]; used[x]=1; PF("? %d\n",x); fflush(stdout); int
l,r; SF("%d",&l); PF("? %d\n",x+n/2); fflush(stdout); SF("%d",&r); if(l==r){ PF("! %d\n",x); exit(0); } a[x]=r-l; } void que(int l,int r){ int mid=(l+r)>>1; ll vall=ask(l); ll valm=ask(mid); ll valr=ask(r); if(vall*valm<0
) que(l,mid); else if(valm*valr<0) que(mid+1,r); } int main(){ SF("%d",&n); if(n%4){ PF("! -1"); return 0; } que(1,n/2); PF("! -1"); }