@xiaoziyao
2021-05-13T09:09:02.000000Z
字数 1321
阅读 1399
解题报告
CF788D Finding lines解题报告:
有条平行于轴的直线条平行于轴的直线,你每次询问可以得到一个点距离其最近的直线距离,在不多于次询问中你需要确定这些直线。
普通的交互题。
考虑这些直线都会与一三象限平分线产生交点,我们可以在这条直线上分治确定这些交点。
具体地,我们每次处理区间的时候询问(为区间中点),如果返回值为那么就确定了一个交点,且继续递归与,否则递归到区间与。
这一部分的询问次数有点难分析(下面纯口胡):考虑一个有线段的区间会在两次询问中找到某条线段,并产生个区间的无用递归(原区间没有这条线段的另一个区间,以及找到这条线段后递归的两个区间),而如果某个区间没有线段,只需要一次询问就可以排除(因为会递归到两个空区间),所以询问次数有一个很松的上界为,但是实际表现甚至跑不满。
找到这些直线与交点后,我们任取一个之前询问不在线段上的点,枚举每个交点,如果在线段上的话就有一条,如果在线段上的话就有一条(注意有可能同时存在)。
这一部分的询问次数上界为。
那么总询问次数最多,似乎在CF上最多只跑到(还是小数据)。
#include<stdio.h>#include<vector>using namespace std;int no;vector<int>ans,X,Y;int ask(int x,int y){printf("0 %d %d\n",x,y);fflush(stdout);int res;scanf("%d",&res);return res;}void solve(int l,int r){if(l>r)return ;int mid=(l+r)>>1,res=ask(mid,mid);if(res==0)ans.push_back(mid),res=1;else no=mid;solve(l,mid-res),solve(mid+res,r);}int main(){solve(-100000000,100000000);for(int i=0;i<ans.size();i++){if(ask(ans[i],no)==0)X.push_back(ans[i]);if(ask(no,ans[i])==0)Y.push_back(ans[i]);}printf("1 %d %d\n",X.size(),Y.size());for(int i=0;i<X.size();i++)printf("%d%c",X[i],i==X.size()-1? '\n':' ');for(int i=0;i<Y.size();i++)printf("%d%c",Y[i],i==Y.size()-1? '\n':' ');return 0;}
