[关闭]
@xiaoziyao 2021-05-13T17:09:02.000000Z 字数 1321 阅读 924

CF788D Finding lines解题报告

解题报告


CF788D Finding lines解题报告:

更好的阅读体验

题意

条平行于轴的直线条平行于轴的直线,你每次询问可以得到一个点距离其最近的直线距离,在不多于次询问中你需要确定这些直线。

分析

普通的交互题。

考虑这些直线都会与一三象限平分线产生交点,我们可以在这条直线上分治确定这些交点。

具体地,我们每次处理区间的时候询问为区间中点),如果返回值那么就确定了一个交点,且继续递归,否则递归到区间

这一部分的询问次数有点难分析(下面纯口胡):考虑一个有线段的区间会在两次询问中找到某条线段,并产生个区间的无用递归(原区间没有这条线段的另一个区间,以及找到这条线段后递归的两个区间),而如果某个区间没有线段,只需要一次询问就可以排除(因为会递归到两个空区间),所以询问次数有一个很松的上界为,但是实际表现甚至跑不满

找到这些直线与交点后,我们任取一个之前询问不在线段上的点,枚举每个交点,如果在线段上的话就有一条,如果在线段上的话就有一条(注意有可能同时存在)。

这一部分的询问次数上界为

那么总询问次数最多,似乎在CF上最多只跑到(还是小数据)。

代码

  1. #include<stdio.h>
  2. #include<vector>
  3. using namespace std;
  4. int no;
  5. vector<int>ans,X,Y;
  6. int ask(int x,int y){
  7. printf("0 %d %d\n",x,y);
  8. fflush(stdout);
  9. int res;
  10. scanf("%d",&res);
  11. return res;
  12. }
  13. void solve(int l,int r){
  14. if(l>r)
  15. return ;
  16. int mid=(l+r)>>1,res=ask(mid,mid);
  17. if(res==0)
  18. ans.push_back(mid),res=1;
  19. else no=mid;
  20. solve(l,mid-res),solve(mid+res,r);
  21. }
  22. int main(){
  23. solve(-100000000,100000000);
  24. for(int i=0;i<ans.size();i++){
  25. if(ask(ans[i],no)==0)
  26. X.push_back(ans[i]);
  27. if(ask(no,ans[i])==0)
  28. Y.push_back(ans[i]);
  29. }
  30. printf("1 %d %d\n",X.size(),Y.size());
  31. for(int i=0;i<X.size();i++)
  32. printf("%d%c",X[i],i==X.size()-1? '\n':' ');
  33. for(int i=0;i<Y.size();i++)
  34. printf("%d%c",Y[i],i==Y.size()-1? '\n':' ');
  35. return 0;
  36. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注