Description

给出一个N个顶点的简单多边形,对于每个顶点,假如它和原点连成的线段只在这个顶点处和多边形相交,就称为满足要求的顶点。你的任务是输出所有满足要求的顶点编号。

Input

第一行一个正整数N。下面N行每行两个不超过106的正整数,依次表示每个顶点的坐标。顶点按照输入顺序用正整数1..N编号,并且顶点保证按照顺时针或逆时针顺序给出。

Output

第一行一个正整数M,表示满足要求的顶点个数。第二行M个正整数,按照升序给出满足要求的顶点编号。
 
对所有点极角排序并离散化,特判极角相同的情况,建线段树,将所有边插到线段树上,最后查询每个点方向的射线与多边形最近的交点。
按极角做扫描线也可以在相同复杂度内实现,但细节可能更多。
  1. #include<bits/stdc++.h>
  2. typedef long long i64;
  3. int min(int a,int b){return a<b?a:b;}
  4. int max(int a,int b){return a>b?a:b;}
  5. const int N=;
  6. char buf[],*ptr=buf;
  7. int _(){
  8. int x=;
  9. while(*ptr<)++ptr;
  10. while(*ptr>)x=x*+*ptr++-;
  11. return x;
  12. }
  13. struct pos{
  14. double x,y;
  15. double val()const{return x+y;}
  16. }xs[N];
  17. double operator*(pos a,pos b){return a.x*b.y-a.y*b.x;}
  18. pos operator-(pos a,pos b){return (pos){a.x-b.x,a.y-b.y};}
  19. int n;
  20. struct vertex{
  21. pos p;
  22. int id,x;
  23. bool operator<(vertex w)const{
  24. double d=p*w.p;
  25. return d?d<:p.val()<w.p.val();
  26. }
  27. }vs[N];
  28. int ps[N],xp=;
  29. bool un[N];
  30. struct itv{
  31. pos a,b;
  32. int l,r;
  33. double operator()(pos&w)const{
  34. return w.val()*(b*a)/(w*(a-b));
  35. }
  36. }is[];
  37. int mx;
  38. void ins(itv&a,itv&b){
  39. if(!a.r)a=b;
  40. else{
  41. int l=max(a.l,b.l),r=min(a.r,b.r);
  42. if(a(xs[l])+a(xs[r])>b(xs[l])+b(xs[r]))a=b;
  43. }
  44. }
  45. void ins(vertex a,vertex b){
  46. itv w=(itv){a.p,b.p,a.x,b.x};
  47. for(int l=a.x+mx-,r=b.x+mx+;r-l!=;l>>=,r>>=){
  48. if(~l&)ins(is[l^],w);
  49. if(r&)ins(is[r^],w);
  50. }
  51. }
  52. int as[N],ap=;
  53. int main(){
  54. fread(buf,,sizeof(buf),stdin);
  55. n=_();
  56. for(mx=;mx<=n+;mx<<=);
  57. for(int i=;i<=n;++i){
  58. vs[i].p.x=_();
  59. vs[i].p.y=_();
  60. vs[i].id=i;
  61. }
  62. std::sort(vs+,vs+n+);
  63. for(int i=,j=;i<=n;i=j){
  64. for(++j;j<=n&&vs[i].p*vs[j].p==;un[vs[j].id]=,++j);
  65. xs[++xp]=vs[i].p;
  66. for(int k=i;k<j;++k)vs[k].x=xp;
  67. }
  68. for(int i=;i<=n;++i)ps[vs[i].id]=i;
  69. ps[]=ps[n];
  70. for(int i=;i<=n;++i){
  71. int a=ps[i-],b=ps[i];
  72. if(a>b)std::swap(a,b);
  73. if(vs[a].x<vs[b].x)ins(vs[a],vs[b]);
  74. }
  75. for(int i=;i<=n;++i)if(!un[vs[i].id]){
  76. for(int w=vs[i].x+mx;w;w>>=)if(is[w].r&&is[w](vs[i].p)<vs[i].p.val()-1e-){
  77. un[vs[i].id]=;
  78. break;
  79. }
  80. }
  81. for(int i=;i<=n;++i)if(!un[i])as[ap++]=i;
  82. printf("%d\n",ap);
  83. for(int i=;i<ap;++i)printf("%d ",as[i]);
  84. return ;
  85. }

bzoj2856: [ceoi2012]Printed Circuit Board的更多相关文章

  1. Printed Circuit Board (board)

    Printed Circuit Board (board) 题目描述 给出一个N个顶点的简单多边形,对于每个顶点,假如它和原点连成的线段只在这个顶点处和多边形相交,就称为满足要求的顶点.你的任务是输出 ...

  2. ZOJ1648 Circuit Board 2017-04-18 20:31 34人阅读 评论(0) 收藏

    Circuit Board Time Limit: 2 Seconds      Memory Limit: 65536 KB On the circuit board, there are lots ...

  3. ZOJ 1648 Circuit Board(计算几何)

    Circuit Board Time Limit: 2 Seconds Memory Limit: 65536 KB On the circuit board, there are lots of c ...

  4. ZOJ1648 Circuit Board(线段相交)

    裸的判断线段相交

  5. kickstart2019 round_C B. Circuit Board

    思路: 这题应该不止一种解法,其中的一种可以看作是leetcode85https://www.cnblogs.com/wangyiming/p/11059176.html的加强版: 首先对于每一行,分 ...

  6. zoj 1648 Circuit Board

    题目:意思就是推断给定的几条线段是否有相交的. 方法:模版吧,有空在来细细学习. 代码: #include <iostream> #include <cstdio> using ...

  7. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  8. COB(Chip On Board) 工艺技术

    COX(Chip On X) •X 基板:  PCB (Printed circuit board)  FPC (Flexible Printed Circuit)  Glass •导线焊接 球形焊接 ...

  9. 特邀美国EMC实战专家Mark来华授课

    “轻松搞定EMC-PCB和系统设计”课程介绍 本次课程特邀美国EMC领域权威专家Mark Montrose主讲,将涵盖满足产品电磁兼容性和信号完整性的基本原理.课程涉及多个领域,不仅仅针对PCB设计, ...

随机推荐

  1. 腾讯云JavaWeb环境配置

    腾讯云服务器Centos7系统配置javaWeb运行环境 java1.8 运行命令列表 yum list java-* 安装相应版本的jdk,一般含有devel的就是真正的jdk,如:java-1.8 ...

  2. 特殊符号 sort_wc_uniq命令 tee_tr_split命令

     *     任意个 任意字符 ?    任意一个字符  #     注释字符   \     转意符   |     管道符  (之前有说过) cut  命令: cut  -d "&quo ...

  3. PTA——猜数字游戏

    PTA 7-24 猜数字游戏 #include <stdio.h> int main() { int num, times; scanf("%d %d", &n ...

  4. Linux下安装Blender

    Blender在Windows下,可以在官方直接下载免安装的版本,下载解压缩就能用. 在Linux下稍微麻烦一点点. 如下3步安装的blender不一定是最新版本,且安装完成后发现设置中文会变为方块. ...

  5. mvc core2.1 Identity.EntityFramework Core 登录 (三)

    Controllers->AccountController.cs 新建 [HttpGet] [AllowAnonymous] public async Task<IActionResul ...

  6. CH5701 开车旅行

    题意 5701 开车旅行 0x50「动态规划」例题 描述 小A和小B决定利用假期外出旅行,他们将想去的城市从1到N编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ...

  7. confluence 为合并的单元格新增一行

    1,先将最后一个结构取消合并单元格 |    | ___ | |    | ___ | | _ | ___ | 2,在最后一行追加一行,将左侧合并 3,将上面取消合并的重新合并即可

  8. UWA 转载

    性能优化,进无止境-内存篇 https://blog.uwa4d.com/archives/optimzation_memory_1.html https://blog.uwa4d.com/archi ...

  9. MySQL全文本搜索

    启用全文本搜索支持 create table text( -> id int not null auto_increment, -> texts text null, -> prim ...

  10. Java Scanner学习记录

    1. Java.util.Scanner可以用来从键盘获取输入 Scanner.next()  只能读取字符,遇到任何的符合都不会输出 Scanner.nextLine()  会完全按照用户输入的st ...