题目大意:

给定n段线段 编号为1~n

接下来m个询问 给定一点

输出离该点最近的线段的最小编号(距离相等时取编号小的)

题解

大致就是

1.坐标范围为(0,2^16-1)

将坐标系划分为2^8*2^8的小块 编号为0~2^8-1

判断线段穿过哪些小块 并用had[ i ][  ]保存穿过 i小块 的所有线段的编号

2.当给定一个点时 找到该点所在的小块

因为最近的线段可能不存在与这个小块

所以暴力 该小块 及其 八联通小块(共九个小块)的线段

#1. 这样可以获得坐标(x,y)所在小块的编号

  1. int getS(double x,double y) {
  2. int a=round(x), b=round(y);
  3. return (b>>)*(<<)+(a>>);
  4. }

1.round()是一个四舍五入的取整函数 (需要注意的是6.5时得到7或6的概率各50%)

2.(b>>8) 获得纵向该点所在的层数  *(1<<8) 获得该层第一个的编号

  (a>>8) 获得横向所在的位置 相加就是 其所在小块的编号了

#2. 计算点到线段的距离

  1. // 点a与点b的距离
  2. double lenPP(P a,P b) {
  3. return sqrt( (a-b).dot(a-b) );
  4. }
  5. // 点c到线段ab的距离
  6. double lenPS(P a,P b,P c) {
  7. if(a==b) return lenPP(a,c);
  8. if((b-a).dot(c-a)<) return lenPP(c,a);
  9. else if((b-a).dot(c-b)>) return lenPP(c,b);
  10. else return abs((b-a).det(c-a))/lenPP(b,a);
  11. }

需要分三种情况

1. c的垂足在ab上 // 向量ab与ac 点积=0

  那么算出 向量ab与ac 组成的平行四边形面积

  除以 ab的长度 就可以 得到 c到ab的距离

2. c的垂足在a左侧 // 向量ab与ac 点积<0

  ac的长度就是c到ab的距离

3. c的垂足在b右侧 // 向量ab与bc 点积>0

  bc的长度就是c到ab的距离

/*

这道题虽然没有出现精度问题

但是计算几何题精度要求高时 下面的地方可能会有问题

  1. 结构体重载时
  2. bool operator == (P p) {
  3. return x-p.x== && y-p.y==;
  4. }
  5. getDis()中
  6. if(dis-ansd<) ...
  7. else if(dis-ansd== ... ) ...

可以改写为

  1. 结构体重载时
  2. bool operator == (P p) {
  3. return abs(x-p.x)<eps && abs(y-p.y)<eps;
  4. }
  5. getDis()中
  6. if(dis-ansd<-eps) ...
  7. else if(abs(dis-ansd)<eps ... ) ...

改写规则为

a<0    ->  a<-eps

a<=0  ->  a<eps

a==0  ->  abs(a)<eps

*/

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int N=(<<)+;
  5. const double eps=1e-;
  6. double add(double a,double b) {
  7. if(abs(a+b)<eps*(abs(a)+abs(b))) return ;
  8. return a+b;
  9. }
  10. struct P {
  11. double x,y;
  12. P(){};
  13. P(double _x,double _y):x(_x),y(_y){};
  14. P operator - (P p) {
  15. return P(add(x,-p.x),add(y,-p.y)); }
  16. P operator + (P p) {
  17. return P(add(x,p.x),add(y,p.y)); }
  18. P operator * (double d) {
  19. return P(x*d,y*d); }
  20. P operator / (double d) {
  21. return P(x/d,y/d); }
  22. bool operator == (P p) {
  23. return x-p.x== && y-p.y==; }
  24. double dot (P p) {
  25. return add(x*p.x,y*p.y); }
  26. double det (P p) {
  27. return add(x*p.y,-y*p.x); }
  28. }s[],e[],aim;
  29. int n,m,ansi;
  30. double ansd;
  31. int mov[]={
  32. -(N-),-(N-)-,-(N-)+, // 上 左上 右上
  33. N-,(N-)-,(N-)+,-,, // 下 左下 右下 左 右 中
  34. };
  35. // 点a与点b的距离
  36. double lenPP(P a,P b) {
  37. return sqrt( (a-b).dot(a-b) );
  38. }
  39. // 点c到线段ab的距离
  40. double lenPS(P a,P b,P c) {
  41. if(a==b) return lenPP(a,c);
  42. if((b-a).dot(c-a)<) return lenPP(c,a);
  43. else if((b-a).dot(c-b)>) return lenPP(c,b);
  44. else return abs((b-a).det(c-a))/lenPP(b,a);
  45. }
  46. vector <int> had[N*N];
  47. int getS(double x,double y) {
  48. int a=round(x), b=round(y);
  49. return (b>>)*(<<)+(a>>);
  50. }
  51. void getDis(int S) {
  52. for(int i=;i<had[S].size();i++) {
  53. int j=had[S][i];
  54. double dis=lenPS(s[j],e[j],aim);
  55. if(dis-ansd<) ansd=dis, ansi=j; // 若存在更小的距离
  56. else if(dis-ansd== && j<ansi) ansi=j; // 距离相等 取更小的编号
  57. }
  58. }
  59. int main()
  60. {
  61. while(~scanf("%d%d",&n,&m)) {
  62. for(int i=;i<n;i++) {
  63. scanf("%lf%lf%lf%lf",&s[i].x,&s[i].y,&e[i].x,&e[i].y);
  64. P v=e[i]-s[i]; // v为s[i]到e[i]的方向向量
  65. v=v/(N-); // 得到相对于小块长度的单位向量
  66. int a=-; /// 防止重复保存
  67. for(int j=;j<N;j++) {
  68. P h=s[i]+v*j; // 从 s[i]开始 v方向上 j倍长度 的坐标
  69. int b=getS(h.x,h.y); // 得到所在块
  70. if(b!=a) had[b].push_back(i); // 保存穿过 b小块 的 i线段
  71. a=b;
  72. }
  73. }
  74. while(m--) {
  75. scanf("%lf%lf",&aim.x,&aim.y);
  76. ansd=1e10;
  77. int S=getS(aim.x,aim.y);
  78. for(int i=;i<;i++) { // 九个小块
  79. int t=S+mov[i];
  80. if(t>= && t<N*N) getDis(t);
  81. }
  82. printf("%d\n",ansi+);
  83. }
  84. }
  85.  
  86. return ;
  87. }

2018北京网络赛 G The Mole /// 分块暴力 点线距离的更多相关文章

  1. 2015北京网络赛 J Scores bitset+分块

    2015北京网络赛 J Scores 题意:50000组5维数据,50000个询问,问有多少组每一维都不大于询问的数据 思路:赛时没有思路,后来看解题报告也因为智商太低看了半天看不懂.bitset之前 ...

  2. 2015北京网络赛 G Boxes BFS+打表

    G Boxes 题意:n个位置摆有n个箱子,每次移动只能把相邻的垒起来,且上面的必须小于下面的.求摆成升序需要移动多少步. 思路:这里的n很小,只有7.但是bfs最快的情况需要2s左右,所以就打表了. ...

  3. hihocode 1584 : Bounce (找规律)(2017 北京网络赛G)

    题目链接 比赛时随便找了个规律,然后队友过了.不过那个规律具体细节还挺烦的.刚刚偶然看到Q巨在群里提到的他的一个思路,妙啊,很好理解,而且公式写起来也容易.OrzQ巨 #include<bits ...

  4. 北京网络赛G BOXES 状态压缩+有序BFS+高维数组判重

    #include <bits/stdc++.h> using namespace std; ]; ][]; ][][]; ][][][]; ][][][][]; ][][][][][]; ...

  5. 2015北京网络赛 G题 Boxes bfs

    Boxes Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/contest/acmicpc2015beijingonl ...

  6. hdu 5038 (2014北京网络赛G 排序水题)

    题意:有n个数字,带入10000 - (100 - ai) ^ 2公式得到n个数,输出n个数中频率最大的数,如果有并列就按值从小到大都输出输出,如果频率相同的数字是全部的n个数,就输出Bad....题 ...

  7. 2018青岛网络赛G - Couleur 区间上的启发式合并

    题意:给出\(a[1...n]\),共\(n\)次操作,每次删除一个位置\(p_i\)(强制在线),此时区间会变为两个分离的区间,求每次操作的最大区间逆序对 首先要知道必要的工具,按权值建立的主席树可 ...

  8. ACM-ICPC 2018北京网络赛-A题 Saving Tang Monk II-优先队列

    做法:优先队列模板题,按步数从小到大为优先级,PASS掉曾经以相同氧气瓶走过的地方就好了 题目1 : Saving Tang Monk II 时间限制:1000ms 单点时限:1000ms 内存限制: ...

  9. 2018北京网络赛D 80days (尺取)

    #1831 : 80 Days 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 80 Days is an interesting game based on Jules ...

随机推荐

  1. python实现线程池(2.4)

    线程池 什么是线程池? 诸如web服务器.数据库服务器.文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务. 构建服务器应用程序的一个过于简单的模型是:每当一个请求到达就 ...

  2. 转-C++之手写strcpy

    转自:strcpy函数的实现 知strcpy函数的原型是: char *strcpy(char *dst, const char *src); 实现strcpy函数 解释为什么要返回char * 假如 ...

  3. 框架-.NET:Spring.Net

    ylbtech-框架-Spring.Net:Spring.Net Spring.NET为建立企业级应用提供了一套轻量级的解决方案.通过Spring.NET,我们可以用统一且透明的方式来配置应用程序.S ...

  4. ffs, fls

    linux内核中的宏ffs(x)   linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/include/asm/bitops.h #define ffs(x) ...

  5. JUC源码分析-集合篇(九)SynchronousQueue

    JUC源码分析-集合篇(九)SynchronousQueue SynchronousQueue 是一个同步阻塞队列,它的每个插入操作都要等待其他线程相应的移除操作,反之亦然.SynchronousQu ...

  6. 数据整理A

  7. 前端跨域实现的几种方式?及使用Nginx反向代理配置。

    早期为了防止CSRF(跨域请求伪造)的攻击,浏览器引入了同源策略(SOP)来提高安全性.而所谓"同源策略",即同域名(domain或ip).同端口.同协议的才能互相获取资源,而不能 ...

  8. pytest的断言、跳过、运行的按需要处理

    def test_one(): assert 1==1 assert 1!=2 assert {'name':'linda','age':19}=={'name':'linda','age':190} ...

  9. 辞职信也要玩出高big

    辞职信尊敬的各位公司领导:值此用人之际,不期请辞,实属不敬.历经四季,余以凡才,承蒙殊待,幸受公司各位领导知遇之恩,得以与诸位贤达公事.时光荏苒,吾经竭力而为,以图报效,虽幸遇领导执手相教,然资质愚钝 ...

  10. 从零开始搭建系统2.4——Jenkins安装及配置

    1.安装wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins.io/redhat-stable/jenkins.reporpm --impo ...