T1 bzoj: [Usaco2010 OPen]Triangle Counting 数三角形

看到这个题n那么大, 于是想到极角排序搞一搞,然而排完序后立马懵逼,完全不知道接下来应该怎么写。。。。

盯了好久题目给的图后全无思路于是手绘图,然后我就发现了秘密。。。。

极角排序后,如果两个点能与另外的某一个点构成黄金三角形,那么那个点必然在这两个点与原点连线的延长线所夹的区间内。

又因为有极角排序,点a[1],a[2]能构成的三角形,换成点a[1],a[3]肯定也可以构成,因为它们的区间一定是包含关系。

于是我们搞出所有a[i],a[i-1]区间内的答案,计算对答案的贡献即可。

正着有i-1个区间包含它,反着有n-i个区间包含它,然后搞一搞就好了。。。

细节什么的参见代码,反正感觉我代码是写丑了,我还算出了j搞了两遍for循环,看他们代码一个个巨短。。。。理应一遍就应该可以了吧。。。。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. #define maxn 100100
  8. #define pi (acos(-1.0))
  9.  
  10. int n,j,tmp,sum;
  11. long long ans;
  12.  
  13. struct point{
  14. double x,y,ang;
  15. }p[maxn];
  16.  
  17. double operator *(point a,point b){return a.x*b.y-a.y*b.x;}
  18.  
  19. bool cmp(point a,point b){
  20. return a.ang<b.ang;
  21. }
  22.  
  23. int main(){
  24. // freopen("input.txt","r",stdin);
  25. // freopen("output.txt","w",stdout);
  26. scanf("%d",&n);
  27. for (int i=;i<=n;i++)
  28. scanf("%lf%lf",&p[i].x,&p[i].y),p[i].ang=atan2(p[i].y,p[i].x);
  29. sort(p+,p+n+,cmp);
  30. for (int i=;i<=n;i++) if (p[i].ang-p[].ang>pi){j=tmp=i;break;}
  31. for (int i=;i<j;i++){
  32. int sum=;
  33. while (p[tmp].ang-p[i].ang<pi && tmp<=n) tmp++,sum++;
  34. ans+=(long long)sum*(i-)*(j-i);
  35. }
  36. for (int i=;i<j;i++) if (p[j].ang-p[i].ang<pi){tmp=i;break;}
  37. for (int i=j+;i<=n;i++){
  38. int sum=;
  39. while (p[i].ang-p[tmp].ang>pi && tmp<j) tmp++,sum++;
  40. ans+=(long long)sum*(i-j)*(n-i+);
  41. }
  42. printf("%lld\n",ans);
  43. return ;
  44. }

T1

T2 poj 3608 Bridge Across Islands

两个多边形间的旋转卡壳,网上给了一大堆代码,一大堆题解,感觉都大同小异,几乎都是国外某大牛的论文翻译过来的。。。。。什么搞出一个ymin,ymax,特别是哪个叉乘while,根本看不懂。。。。。线段之间的距离真的可以用叉乘吗。。。。。(蒟蒻求解。。。)

于是我有一种想法,首先在多边形P上随便找到一条边,然后找到多边形Q上距离最近的点,然后将多边形P上的该边跳到它的邻边,同时直接移动多边形Q上找到的点,和两边的点比较,之后移动,直到移动到下一个点的距离比该点距离大就停止。然后在多边形Q上也做一次类似的即可。然后每次移动更新答案,就完了。。。。。

感觉这样做正确性也十分显然,因为对于任意一条边,另一个多边形的所有点距离它都是单峰的。于是对于当前点,它一定能找到距离最近的点。注意这里并不用两个指针扫,只需要将当前点与左右两边比较就行了。因为不可能出现左右两边的点都比当前点更优的情况,因为当前点一定是左右两边的某个点转移过来的,而对于当前的边,它一定会比至少一条边优。(这个性质稍微分情况讨论一下也可以得出),同时因为边每次只是跳到邻边,因此绝对不会出现每次移动n/2的情况,因为这个过程类似于旋转卡壳实现过程,时间复杂度也是可以保证的,常数好像大了一些。。。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. #define maxn 100010
  8. #define inf 1e9
  9.  
  10. int n,m;
  11. double ans;
  12.  
  13. struct point{
  14. double x,y;
  15. }p[maxn],q[maxn];
  16.  
  17. struct line{
  18. point from,to;
  19. }lp[maxn],lq[maxn];
  20.  
  21. point operator -(point a,point b){return (point){a.x-b.x,a.y-b.y};}
  22. double operator *(point a,point b){return a.x*b.y-a.y*b.x;}
  23.  
  24. double sqr(double x){return x*x;}
  25. double dis(point a,point b){return sqr(a.x-b.x)+sqr(a.y-b.y);}
  26.  
  27. double point_line_dis(point a,line b){
  28. if (dis(b.to,b.from)+min(dis(a,b.to),dis(a,b.from))<max(dis(a,b.to),dis(a,b.from)))
  29. return sqrt(min(dis(a,b.to),dis(a,b.from)));
  30. else return fabs((b.to-a)*(b.from-a))/sqrt(dis(b.to,b.from));
  31. }
  32.  
  33. void solvep(){
  34. double dist=inf;int pos;
  35. for (int i=;i<=m;i++){
  36. double tmp=point_line_dis(q[i],lp[]);
  37. if (tmp<dist)
  38. dist=tmp,pos=i;
  39. }
  40. ans=min(ans,dist);
  41. for (int i=;i<=n;i++){
  42. while (point_line_dis(q[pos],lp[i])>point_line_dis(q[pos+],lp[i])) pos==m?pos=:pos++;
  43. while (point_line_dis(q[pos],lp[i])>point_line_dis(q[pos-],lp[i])) pos==?pos=m:pos--;
  44. ans=min(ans,point_line_dis(q[pos],lp[i]));
  45. }
  46. }
  47.  
  48. void solveq(){
  49. double dist=inf;int pos;
  50. for (int i=;i<=n;i++){
  51. double tmp=point_line_dis(p[i],lq[]);
  52. if (tmp<dist)
  53. dist=tmp,pos=i;
  54. }
  55. ans=min(ans,dist);
  56. for (int i=;i<=m;i++){
  57. while (point_line_dis(p[pos],lq[i])>point_line_dis(p[pos+],lq[i])) pos==n?pos=:pos++;
  58. while (point_line_dis(p[pos],lq[i])>point_line_dis(p[pos-],lq[i])) pos==?pos=n:pos--;
  59. ans=min(ans,point_line_dis(p[pos],lq[i]));
  60. }
  61. }
  62.  
  63. int main(){
  64. while (scanf("%d%d",&n,&m)!=EOF){
  65. ans=inf;
  66. if (n== && m==) break;
  67. for (int i=;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
  68. for (int i=;i<=m;i++) scanf("%lf%lf",&q[i].x,&q[i].y);
  69. p[n+]=p[],q[m+]=q[];
  70. for (int i=;i<=n;i++) lp[i].from=p[i],lp[i].to=p[i+];
  71. for (int i=;i<=m;i++) lq[i].from=q[i],lq[i].to=q[i+];
  72. solvep();
  73. solveq();
  74. printf("%.6f\n",ans);
  75. }
  76. return ;
  77. }

T2

T3 一道不知道哪里可以交的题目

题目大意:平面内有n个点,p1,p2,p3...pn。在平面内选m个点,并将p[]分成m段区间,定义d为每一段区间内的点p与找到的点q的距离的最大值,让所有区间d的最大值最小,并输出这个d。

看到最大值最小,考虑二分,二分这个答案d,然后考虑如何去check。

其次可以考虑贪心,因为已经得出了这个d,然后让这个区间内的所有点到找到的点的距离都不超过d,可以考虑最小圆覆盖,如果当前点在已经得到的圆内,就直接加,否则得到新的圆,如果新的圆的半径大于了这个二分的d,就可以新分一段,再去做最小圆覆盖,如果段数要大于m,就可以return 0了。

但以保证最小圆覆盖的复杂度必须要random_shuffle(),所以check()不能直接二分+最小圆覆盖,这样复杂度会爆炸,可以用倍增把二分的范围卡在logn之内再上二分就能(卡)过了。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. #define maxn 100010
  8. #define inf 2000000
  9. #define double long double
  10. const double eps=1e-;
  11.  
  12. int n,m;
  13.  
  14. struct point{
  15. double x,y,r;
  16. }a[maxn],b[maxn],O;
  17.  
  18. double sqr(double x){return x*x;}
  19. double dis(point a,point b){return sqr(a.x-b.x)+sqr(a.y-b.y);}
  20.  
  21. void getcircle(int i,int j){
  22. O.r=dis(b[i],b[j])/;
  23. O.x=(b[i].x+b[j].x)/;
  24. O.y=(b[i].y+b[j].y)/;
  25. }
  26.  
  27. void getcircle(int i,int j,int k){
  28. double a,c,d,e,f,g;
  29. a=*(b[i].x-b[j].x);
  30. g=*(b[i].y-b[j].y);
  31. c=sqr(b[i].x)-sqr(b[j].x)+sqr(b[i].y)-sqr(b[j].y);
  32. d=*(b[i].x-b[k].x);
  33. e=*(b[i].y-b[k].y);
  34. f=sqr(b[i].x)-sqr(b[k].x)+sqr(b[i].y)-sqr(b[k].y);
  35. O.x=(c*e-g*f)/(a*e-g*d);
  36. O.y=(c*d-a*f)/(g*d-a*e);
  37. O.r=dis(O,b[i]);
  38. }
  39.  
  40. bool incircle(int i){
  41. return dis(b[i],O)-O.r<=eps;
  42. }
  43.  
  44. bool judgecircle(int l,int r,double limit){
  45. // if (l==r) return 1;
  46. int cnt=;
  47. for (int i=l;i<=r;i++) b[++cnt]=a[i];
  48. random_shuffle(b+,b+cnt+);
  49. getcircle(,);
  50. if (O.r>sqr(limit)+eps) return ;
  51. for (int i=;i<=cnt;i++)
  52. if (!incircle(i)){
  53. getcircle(,i);
  54. if (O.r>sqr(limit)+eps) return ;
  55. for (int j=;j<i;j++)
  56. if (!incircle(j)){
  57. getcircle(i,j);
  58. if (O.r>sqr(limit)+eps) return ;
  59. for (int k=;k<j;k++)
  60. if (!incircle(k)){
  61. getcircle(i,j,k);
  62. if (O.r>sqr(limit)+eps) return ;
  63. }
  64. }
  65. }
  66. return ;
  67. }
  68.  
  69. bool check(double limit){
  70. int pos=,num=;
  71. for (int i=;i<=n;i=pos+){
  72. int len=;
  73. while (i+(len<<)-<=n && judgecircle(i,i+(len<<)-,limit)) len<<=;
  74. int l=i+len-,r=min(i+(len*)-,n);
  75. while (l<r){
  76. int mid=(l+r)>>;
  77. if (judgecircle(i,mid+,limit)) l=mid+;
  78. else r=mid;
  79. }
  80. pos=r,num++;
  81. if (num>m) return ;
  82. }
  83. return ;
  84. }
  85.  
  86. int main(){
  87. // freopen("input.txt","r",stdin);
  88. // freopen("output.txt","w",stdout);
  89. scanf("%d%d",&n,&m);
  90. for (int i=;i<=n;i++)
  91. scanf("%Lf%Lf",&a[i].x,&a[i].y);
  92. double l=,r=inf;
  93. while (l+1e-<=r){
  94. double mid=(l+r)/;
  95. if (check(mid)) r=mid;
  96. else l=mid;
  97. }
  98. printf("%.6Lf\n",l);
  99. return ;
  100. }

T3

2016.08.07计算几何总结测试day2的更多相关文章

  1. 2016.08.06计算几何总结测试day1

    T1 bzoj1132[POI2008]TRO 还是太弱了....测试时看到这题直接懵逼,极角排序什么的根本想不起来,只会n^3暴力怎么破......不过竟然有84.....QAQ 正解是n^2log ...

  2. 最新版Theos.2016.08的安装方法

    http://bbs.pediy.com/showthread.php?t=212425 标题: [翻译]手把手安装最新版Theos.2016.08作者: roysue时间: 2016-08-26,1 ...

  3. Python array,list,dataframe索引切片操作 2016年07月19日——智浪文档

    array,list,dataframe索引切片操作 2016年07月19日——智浪文档 list,一维,二维array,datafrme,loc.iloc.ix的简单探讨 Numpy数组的索引和切片 ...

  4. http://tedhacker.top/2016/08/05/Spring%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/

    http://tedhacker.top/2016/08/05/Spring%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%9 ...

  5. ArcEngine中打开各种数据源(WorkSpace)的连接http://www.cnblogs.com/feilong3540717/archive/2011/08/07/2129906.html

    ArcEngine中打开各种数据源(WorkSpace)的连接 ArcEngine中打开各种数据源(WorkSpace)的连接 (SDE.personal/File.ShapeFile.CAD数据.影 ...

  6. 新手C#异常的学习2018.08.07

    异常是在程序执行期间出现的问题.C# 中的异常是对程序运行时出现的特殊情况的一种响应,比如尝试除以零. class Program { static void Main(string[] args) ...

  7. 2016.07.15——istringstream测试

    istringstream测试 1.istringstream strcin(str),字符串(str)可以包括多个单词,单词之间使用空格分开 #include "stdafx.h" ...

  8. [2016.08.09]文本替换专家 v5.2

    软件名称:文本替换专家最新版本:v5.2软件授权:共享软件发布日期:2016.01.18文件大小:650KB操作系统:XP/2003/Win7/Win2008开发人员:胡洪祥版权所有:胡洪祥

  9. 2016 08 27 印刷菜单增加sql语句

    insert into `module` (`ID`, `CONSONANTCODE`, `CREATEDATE`, `DESCRIPTION`, `HANDLER`, `HASCHILD`, `IC ...

随机推荐

  1. linux中grep和egrep的用法

    1. grep简介 grep (global search regular expression_r(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大 ...

  2. c c++ 函数入口和出口的hook(gcc 编译选项),然后打印出函数调用关系的方法

    GCC Function instrumentation机制可以用来跟踪函数的调用关系,在gcc中对应的选项为“-finstrument-functions”.可查看gcc的man page来获取更详 ...

  3. 巧用TAG属性保存对象的指针

    指针的数据类型是整型,一个指针就是一个整型的数值. 所以凡整型的变量(这个整型的变量可以是声明在INI文件中,也可以是声明在函数中的)也好,对象的整型的属性也好,都可以用来存储一个指针. 但对象往往没 ...

  4. Apache CXF框架结构和基本原理(转)

    原文链接:http://blog.sina.com.cn/s/blog_6182547f01017pak.html CXF旨在为服务创建必要的基础设施,它的整体架构主要由以下几个部分组成: 1.Bus ...

  5. Lua 第一个应用程序 Hello World

    lua 开发环境的搭建 现已windows系统为例,演示一下lua环境的搭建. Lua_v5.1.4 下载地址 http://code.google.com/p/luaforwindows/ 点击&q ...

  6. js、jQuery操作input大全 不断完善

    工作中经常用到的,不断更新中... jquery获取单选按钮的值:$("input[name='stageName']:checked").val(); 删除select某几个op ...

  7. C# 算速表达式

              public object ComputeExpression(string expression)         {             var result = new  ...

  8. cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发

     cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发 的产生 视持续更新中.... 视频存放地址例如以下:http://ipd.pps.tv/user/1058663622     ...

  9. C++实现建立和一二进制树的三个递归遍历

    说明:这篇文章是学习交流,转载请注明出处,欢迎转载! 二叉树是一种常见的数据结构.二叉树的遍历也是家常便饭的事了,这里仅仅写出一个完整的能够执行的C++代码来随便建立一个例如以下图所看到的的二叉树,建 ...

  10. 如何编译libcurl

    1. Android •1.1配置 •1.2 Make •1.3的参数配置 2.iOS 3.windows 4.关于头文件 注释 本文档介绍了如何为Android,iOS和Windows编译libcu ...