cf1153E 二分思维交互

恶臭的交互题

/*
一个结论:一个矩形将空间分割成两部分,如果开头结尾都在一个部分内,那么穿过矩形边框的线条数就是偶数,反之就是奇数
通过这个结论来进行判断
    先询问999次将两个x坐标确定,方法是询问(1,X)(n,X)如果结果是奇数,那么就有个点在这里,反之没有,或者是两个点都在X上
    同理询问出两个y坐标
如果结果是两个x,两个y,那么需要确定是(x1,y1)(x2,y2)还是(x1,y2)(x2,y1),这个只要单点询问一次即可
如果结果是一个x,或者一个y(不可能出现两个x都相等,或者y都相等的情况)那么需要在二分再找一次x
    在其中一条线上二分找一下就行了 
*/
#include<bits/stdc++.h>
using namespace std;
int ask(int x1,int y1,int x2,int y2){
    cout<<"? "<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<endl;
    cout.flush();
    int res;
    cin>>res;
    return res;
    cout.flush();
}

int main(){
    int x1=0,y1=0,x2=0,y2=0;
    int n;cin>>n;
    for(int i=1;i<=n;i++){
        int res=ask(1,i,n,i);
        if(res%2){
            if(y1)y2=i;
            else y1=i;
        }
        res=ask(i,1,i,n);
        if(res%2){
            if(x1)x2=i;
            else x1=i;
        }
    }
    if(x1 && y1 && x2 && y2){
        int res=ask(x1,y1,x1,y1);
        if(res%2)
            cout<<"! "<<x1<<" "<<y1<<" "<<x2<<" "<<y2;
        else 
            cout<<"! "<<x1<<" "<<y2<<" "<<x2<<" "<<y1;
        return 0;
    }
    if(x1==0){
        int l=1,r=n,mid,ans=1;
        while(l<=r){
            mid=l+r>>1;
            if(ask(1,y1,mid,y1)%2)//如果[1,mid]是偶数 
                ans=mid,r=mid-1;
            else l=mid+1;
        }
        cout<<"! "<<ans<<" "<<y1<<" "<<ans<<" "<<y2<<endl; 
    } 
    else if(y1==0){
        int l=1,r=n,mid,ans=1;
        while(l<=r){
            mid=l+r>>1;
            if(ask(x1,1,x1,mid)%2)//如果[1,mid]是偶数 
                ans=mid,r=mid-1;
            else l=mid+1;
        }
        cout<<"! "<<x1<<" "<<ans<<" "<<x2<<" "<<ans<<endl; 
    }
    
} 

 

posted on 2019-04-16 19:19  zsben  阅读(188)  评论(0编辑  收藏  举报

导航