题意:

给出一个 NNN 个点的凸包,QQQ 次询问,每次给出一个 idxidxidx 和 kkk,表示现有一根长度无限的垂直 (P[idx],P[idx+1])(P[idx],P[idx+1])(P[idx],P[idx+1]) 向量且距离 P[idx]P[idx]P[idx] 为 kkk 的垂直线。先问这根垂直线倒落时凸包上第一个被碰到的点,如果第一个被碰到的是直线,则输出两个点。(1≤n≤105,1≤Q≤105)(1\leq n\leq 10^5,1\leq Q\leq 10^5)(1≤n≤105,1≤Q≤105)


思路:

稍微画图模拟一下就可以发现,最终倒在哪个点上取决于凸包上的点与这个点连线,连线之后与 (P[idx],P[idx+1])(P[idx],P[idx+1])(P[idx],P[idx+1]) 之间的夹角大小,夹角最大的点即为第一个碰到的点。若有两个相同大的点,即碰到的是直线。

这个夹角是先增后减的,因此不能进行二分,而是三分,而且是整数三分。而整数三分的精髓就是先三分到大致区间,然后在确定的小区间内暴力求解。

但是直接判断角度不好处理,我们转化成向量的叉乘进行计算,判断大小是变大还是变小即可。


总结:

  1. 计算几何中判断大小的问题,尽量转化成叉积或者点积进行计算。
  2. 整数三分是先三分到一个小范围,然后在小范围内直接暴力。

代码:

#include <bits/stdc++.h>
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
#define LOG3(x1,x2,y1,y2,z1,z2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << " , " << z1 << ": " << z2 << endl;
typedef long long ll;
typedef double db;
const int N = 1e5+100;
const int M = 1e5+100;
const db EPS = 1e-9;
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign((cross(p1,p2,p3)))
using namespace std;inline int sign(db a) {return a < -EPS ? -1 : a > EPS; }
inline int cmp(db a,db b) {return sign(a-b);}struct Point{db x,y;Point() {}Point(db _x, db _y) : x(_x), y(_y) {}Point operator-(Point p) {return {x-p.x,y-p.y};}db dot(Point p) {return x*p.x+y*p.y;}db det(Point p) { return x*p.y-y*p.x; } //叉积db abs() { return sqrt(abs2()); }db abs2() { return x*x+y*y; }db disTo(Point p) { return (*this-p).abs(); }
}P[N];int T,Q;int calc(Point p2,Point p3,Point p4){Point t1 = p3-p2, t2 = p4-p2;return sign(t2.det(t1));
}int main()
{scanf("%d%d",&T,&Q);rep(i,0,T-1) scanf("%lf%lf",&P[i].x,&P[i].y);int n = T;rep(i,1,Q){int pos; db x; scanf("%d%lf",&pos,&x);db len = P[pos].disTo(P[(pos+1)%n]);db tx = ((db)(P[(pos+1)%n].x-P[pos].x)*(db)x/len)+P[pos].x;db ty = ((db)(P[(pos+1)%n].y-P[pos].y)*(db)x/len)+P[pos].y;int l = 1, r = T-1, lmid, rmid;while(r-l >= 15){lmid = l+(r-l)/3;rmid = r-(r-l)/3;if(calc({tx,ty},P[(pos+lmid)%n],P[(pos+rmid)%n]) == 1){l = lmid;}else r = rmid;}int indx1 = 1, indx2 = 0;rep(k,l,r){int jud = calc({tx,ty},P[(pos+k)%n],P[(pos+indx1)%n]);if(jud == -1) indx1 = k, indx2 = 0;else if(jud == 0) indx2 = k;}if(indx2 == 0) printf("%d\n",(indx1+pos)%n);else printf("%d %d\n",(indx1+pos)%n,(indx2+pos)%n);}return 0;
}

【Gym-100889 H】Hitting Points【凸包三分】相关推荐

  1. Gym - 100889H Hitting Points 计算几何+三分+二分

    题目链接 Hitting Points 题意 按逆时针顺序给你二维平面上严格凸包的n个点,编号0到n-1, 有q次询问, 每次询问确定一个编号为idx的基础点, 以idx和(idx+1)%n构成的向量 ...

  2. gym 102875 H. Happy Morse Code

    gym 102875 H. Happy Morse Code 题意: 一个长度为n的字符串,现在给你m个小字符串,问小字符串拼成大字符串有多少种方法? 答案mod128 题解: 其实也不难,但是本人对 ...

  3. gym/226036-F. Two Points【三分查找】

    F. Two Points There are two points (x1, y1) and (x2, y2) on the plane. They move with the velocities ...

  4. [GYM 100492A] Average Convex Hull 凸包好题

    大致题意: 给出一个点集,其中有一个点有相同的几率会被删除,求删除之后的点集够成的凸包上的点的平均数. 首先看到题目,可以考虑枚举删除的点,将其凸包上前后两点以及两点间凸包内所有点构建凸包,因为凸包内 ...

  5. BZOJ 3203 Sdoi2013 保护出题人 凸包+三分

    题目大意:太长自己看 令sumi表示第i个僵尸以及之前的僵尸的体力总和.disi表示第i个僵尸与房屋的初始距离 我们发现我们能消灭一个僵尸当且仅当y>=sumidisi 那么我们要求的显然就是m ...

  6. Codeforces Gym 100114 H. Milestones 离线树状数组

    H. Milestones Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descripti ...

  7. hdu 4717 The Moving Points(三分+计算几何)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4717 说明下为啥满足三分: 设y=f(x) (x>0)表示任意两个点的距离随时间x的增长,距离y ...

  8. Gym - 101492 F. Hitting the target(几何)

    http://codeforces.com/gym/101492/problem/F 刚开始的时候按照矩形来做,wa几发之后才知道需要按照圆来做,需要计算一下dis距离. #include<io ...

  9. GYM 101350 H. Mirrored String I

    题目描述 The gorillas have recently discovered that the image on the surface of the water is actually a ...

  10. Gym - 102460L Largest Quadrilateral(几何-凸包+旋转卡壳求最大的四边形面积)

    题目链接:点击查看 题目大意:在笛卡尔坐标系上给出 n 个点,要求选出四个点,使得组成的四边形面积最大,求出这个最大的面积,注意此处组成的四边形不是严格意义上的四边形,只需要选四个点就行 题目分析:首 ...

最新文章

  1. solr安装-tomcat+solrCloud构建稳健solr集群
  2. 使用Networkx进行图的相关计算——黑产集团挖掘,我靠,可以做dns ddos慢速攻击检测啊...
  3. mybatis框架入门程序:演示通过mybatis实现数据库的插入操作中实现返回结果的获取...
  4. 判断不为空和不为空串的方法java
  5. nginx 直接在配置文章中设置日志分割
  6. include动作与include指令的区别
  7. APUE读书笔记-08进程控制(08)
  8. deepin(debian)下使用Git
  9. [转载]i++是否是线程安全的?
  10. python实训day7
  11. RPM、SRPM和YUM,linux包rpm包管理工具
  12. matlab单元刚度矩阵整合成整刚,空间四面体单元刚度矩阵的Matlab向量化集成.pdf...
  13. 手机双拼输入法下的智能纠错
  14. EndNote X7 for Mac破解版
  15. java 鼠标驱动模拟,dd虚拟键盘鼠标模拟软件
  16. matlab 表示希腊字母yita,数学罗马符号_常用数学的罗马符号和拉丁符号有什么哪些_淘题吧...
  17. 哪个软件能代替斐讯路由_斐讯路由器最新版本|好用的路由器管理软件_最火手机站...
  18. 云原生时代,为什么基础设施即代码(IaC)是开发者体验的核心?
  19. 【python教程入门学习】Python 集成开发环境(IDE): VS Code
  20. hiredis使用简介

热门文章

  1. word文档总让正文与目录分开在不同的页——分页符的使用
  2. 如何去掉桌面图标上的小箭头
  3. 病毒周报(100201至100207)
  4. linux的pending状态怎么退出,状态显示Pending Contract
  5. gif 动态加载_用 python 实现切割视频,加入水印,压缩并转成 gif !
  6. 面试题ajax干什么的,ajax面试题
  7. 看书学python靠谱吗_自学Python靠谱吗?
  8. mybatis mysql触发器_MyBatis创建Oracle触发器
  9. mysql 8.0安装_MySQL5.7升级到8.0过程详解
  10. python数据分析:Numpy