专栏文章
题解:CF1153E Serval and Snake
CF1153E题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mints1n8
- 此快照首次捕获于
- 2025/12/02 08:13 3 个月前
- 此快照最后确认于
- 2025/12/02 08:13 3 个月前
首先非常困难的一点就是要注意到当回答为奇数时,说明有恰好一个端点(头尾)在矩形里。
感性理解一下,没有端点就是在中间,肯定是从外面进来再出去,几个进来出去肯定就是偶数。要不然就是头尾都在,就少一个进来出去。
考虑枚举行,找到为奇数的两行。现在横坐标确定了,直接在行上二分就行。要不然头尾都在一行,再枚举列,然后二分。这样最多的询问次数是 ,刚好倒闭。
然后你发现在枚举列的时候,第二列是不用二分的,因为横坐标一定相同。这下就过了。
代码:
CPP#include<bits/stdc++.h>
#define i64 long long
#define L(a,b,c,d) for(int a=b;a<=c;a+=d)
#define R(a,b,c,d) for(int a=b;a>=c;a-=d)
using namespace std;
const int N=1e5+5;
void solve();
int n,p;
pair<int,int> a[3];
signed main(){
int Test=1;
// scanf("%d",&Test);
while(Test--) solve();
return 0;
}
int query(int x1,int y1,int x2,int y2){
int s;
cout<<"? "<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<endl;
cin>>s;
return s;
}
int bs1(int k){
int l=0,r=n+1,m;
while(l+1<r){
m=(l+r)>>1;
if(query(k,l+1,k,m)&1) r=m;
else l=m;
}
return r;
}
int bs2(int k){
int l=0,r=n+1,m;
while(l+1<r){
m=(l+r)>>1;
if(query(l+1,k,m,k)&1) r=m;
else l=m;
}
return r;
}
void solve(){
cin>>n;
L(i,1,n,1){
int s=query(i,1,i,n);
if(s&1) a[++p]={i,bs1(i)};
}
if(!p){
L(i,1,n,1){
int s=query(1,i,n,i);
if(s&1){
if(!p) a[++p]={bs2(i),i};
else a[++p]={a[1].first,i};
}
}
}
cout<<"! "<<a[1].first<<" "<<a[1].second<<" "<<a[2].first<<" "<<a[2].second<<endl;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...