Codeforces Round #551 (Div. 2) E 交互

https://codeforces.com/contest/1153/problem/E

题意

边长为n的正方形里面有一条蛇,每次可以询问一个矩形,然后会告诉你蛇身和矩形相交有几部分,你需要在最多2019询问中知道蛇的头和尾

题解

  • 假如相交奇数部分,那么头和尾一定有一个在矩形里面,假如为偶数部分,头和尾都在里面或者都不在
  • 利用上述性质,对每一行进行询问即(1,1)(i,n) (999次)
    • 假如存在头尾不在同一行,则对列进行两次二分就可以分别找到头和尾(2*10次)
    • 假如头尾在同一行,那么就要从列开始找(999次),最后对行进行二分(2*10次)
  • 最多2018次,orz...

代码

#include<bits/stdc++.h>

using namespace std;
int ask(int X1,int Y1,int X2,int Y2){
    printf("? %d %d %d %d\n",X1,Y1,X2,Y2);
    fflush(stdout);
    int tp;
    scanf("%d",&tp);
    return tp;
}
int n,tp,X1,X2,Y1,Y2;
vector<int>o;
int main(){
    cin>>n;
    for(int i=1;i<n;i++){
        tp=ask(1,1,i,n);
        if(tp&1)o.push_back(i);
    }
    if(!o.empty()){
        int l=1,r=n;
        while(l<r){
            int mid=(l+r)/2;
            tp=ask(1,1,o.front(),mid);
            if(tp%2==0)l=mid+1;
            else r=mid;
        }
        Y1=l;
        l=1;r=n;
        while(l<r){
            int mid=(l+r)/2;
            tp=ask(o.back()+1,1,n,mid);
            if(tp%2==0)l=mid+1;
            else r=mid;
        }
        Y2=l;
        printf("! %d %d %d %d\n",o.front(),Y1,o.back()+1,Y2);
    }else{
        for(int i=1;i<n;i++){
            tp=ask(1,1,n,i);
            if(tp&1)o.push_back(i);
        }
        int l=1,r=n;
        while(l<r){
            int mid=(l+r)/2;
            tp=ask(1,1,mid,o.front());
            if(tp%2==0)l=mid+1;
            else r=mid;
        }
        X1=l;
        l=1;r=n;
        while(l<r){
            int mid=(l+r)/2;
            tp=ask(1,o.back()+1,mid,n);
            if(tp%2==0)l=mid+1;
            else r=mid;
        }
        X2=l;
        printf("! %d %d %d %d\n",X1,o.front(),X2,o.back()+1);
    }
}

猜你喜欢

转载自www.cnblogs.com/VIrtu0s0/p/10811148.html