ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【洛谷1452】【模板】旋转卡壳

2021-03-05 20:34:55  阅读:208  来源: 互联网

标签:洛谷 int -- 卡壳 1452 operator return Con define


点此看题面

  • 给定平面上\(n\)个点,要求你求出它们所构成凸包的直径。
  • \(n\le5\times10^4\)

旋转卡壳模板

一些基础的定义(例如切线、对踵点之类的)就懒得写了。

据说旋转卡壳一般来说都有两种写法,而我自然选择的是其中相对简单的那一种。

考虑如果我们找到了最优状态下的一对切线,把它们同时旋转到与这两个点的某一条邻边相切,那么对面的那个点,必然是与这条边距离最大的点。

然后就可以发现一个很好的性质,凸包上每个点与一条边的距离是满足先增后减的,也就是具有单调性。

而且,如果我们按顺序枚举每一条边,最远的那个点必然是满足单调移动的。

因此我们只要在枚举边的同时利用双指针维护好最远的点就可以做到\(O(n)\)复杂度了(然而求凸包的复杂度是\(O(nlogn)\)的)。

在边确定的时候,要比较距离的大小,其实可以比较与这条边一起构成的三角形面积的大小,直接叉积计算即可。

代码:\(O(nlogn)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 50000
using namespace std;
int n;struct P
{
	int x,y;I P(CI a=0,CI b=0):x(a),y(b){}
	I P operator + (Con P& o) Con {return P(x+o.x,y+o.y);}
	I P operator - (Con P& o) Con {return P(x-o.x,y-o.y);}
	I int operator ^ (Con P& o) Con {return x*o.y-y*o.x;}
	I bool operator < (Con P& o) Con {return x^o.x?x<o.x:y<o.y;}
	I int L2() {return x*x+y*y;}
}p[N+5];
int T;P s[N+5];I void Get()//求凸包
{
	#define pd(A,B,C) (((C-B)^(B-A))>0||(((C-B)^(B-A))==0&&(A<B)==(B<C)))//平行也需要弹去
	RI i;for(sort(p+1,p+n+1),i=1;i<=n;s[++T]=p[i++]) W(T>1&&pd(s[T-1],s[T],p[i])) --T;
	for(i=n-1;i;s[++T]=p[i--]) W(T>1&&pd(s[T-1],s[T],p[i])) --T;--T;
}
I void Rotate()//旋转卡壳
{
	RI i,j,t=(p[1]-p[n]).L2();for(i=1,j=3;i<=T;++i)//枚举每一条边
	{
		W(((s[i+1]-s[i])^(s[j]-s[i]))<((s[i+1]-s[i])^(s[j%T+1]-s[i]))) j=j%T+1;//双指针维护最远点
		t=max(t,max((s[j]-s[i]).L2(),(s[j]-s[i+1]).L2()));//与两端点距离
		t=max(t,max((s[j%T+1]-s[i]).L2(),(s[j%T+1]-s[i+1]).L2()));//最远点可能有两个
	}printf("%d\n",t);
}
int main()
{
	RI i;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d%d",&p[i].x,&p[i].y);
	return Get(),Rotate(),0;
}

标签:洛谷,int,--,卡壳,1452,operator,return,Con,define
来源: https://www.cnblogs.com/chenxiaoran666/p/Luogu1452.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有