zoukankan      html  css  js  c++  java
  • 【洛谷1452】【模板】旋转卡壳

    点此看题面

    • 给定平面上(n)个点,要求你求出它们所构成凸包的直径。
    • (nle5 imes10^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
    ",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;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    confluence的安装、破解和汉化
    Linux学习经验集锦
    MFS 分布式文件系统
    MFS
    Docker 搭建 WordPress
    ansible入门
    docker搭建pxc集群与haproxy负载均衡
    mysql-proxy 实现读写分离
    Linux内核学习总结
    lab8:理解进程调度时机跟踪分析进程调度与进程切换的过程
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Rotate.html
Copyright © 2011-2022 走看看