計算幾何学的な回転スタックコンテンツは、最遠点のペアを得るために使用される平面に属します。
まず、最遠点は最初、面内のn個の点のために、凸包上になければならない2つの点を証明するグラハム走査方式、$の複雑さは、O(nlogn)$を使用して凸包上の全ての点を見つけることは容易です。次に、m個の点遠い点を仮定し、N、Mポイントおよびn最も遠い距離に、示さL1およびL2としてパッケージの凸面側の2つの設定点Nは、直線L1、L2の距離DISをm個(M、L)とDIS(M、L2)、次にエッジ距離L1又はL2に点nが遠い凸包である必要があり、他の凸包は、エッジ距離の存在を指していないと、その凸包よりも大きいです。即ち、MAX(DIS(M、L)、DIS(M、L2))pは凸包上の点であり、> = DIS(P、L)は、Lは、凸包上のエッジです。それは証明するのは簡単ですブログの多くが書かれている読んで、私はそこに2日間レン下目黒カードのために先週許可ウェルカムメッセージに答えることができ、説明するために非常に大きな神に嘆願しました。
探索点を反時計回りに最も遠い点P1、L2、L1、反時計回りに点最も遠い距離L2点P1とP1またはまでの距離ならば、続いて、回転は、エッジL1ため、スタックの本質でありますP2、すなわち、MAX(DIS(L2、P1)、DIS(L2、P2))> = DIS(L2、p)は、pは凸包上の任意の点です。したがって、時間的に対応する点も反時計回りに列挙反時計回り側を移動させることができるだけつつ。
例poj2187は、この質問データは、多くの点が、ランダムであってもよいが、凸包上の計算点の数が非常に少なく、実際に任意の2つの間の凸包列挙距離があってもよいが、データサイズ制限4E5複合体であります$ O(N ^ {2})$で、データ構造は、すべての点がパッケージ上にバンプであることができ、それはオフスナップ、回転が立ち往生正の解です。
書式#include <iostreamの> の#include <cmath> の#include <アルゴリズム> 使用して 名前空間はstdを、 typedefの長い 長いLL。 typedefの長い ダブルLD; typedefの符号なしの長い 長いULL。 typedefのペア < int型、int型 > PII。 #define担当者(I、x、y)がため(I = xをint型、I yを<; I ++) の#define REPT(I、x、y)がため(I = xをint型、iは= yと<; iは++) の#define当たり(I、x、y)は(I = xをint型; I> = Y; i--)のため の#define PB一back の#define make_pair融点 の#defineをFiの第一 の#define SE第二 の#defineド(X)COUT << #X <<」= "<< X << ENDL の#define DD(X)COUT << #X <<" = "<< X <<" 「 の#define MES(B)のmemset(A、B、はsizeof A) のconst int型 INF = 0x3f3f3f3f 。 const int型 MAXN = 5E4 + 5 。 PIIポイント[MAXN]。// 存放点、下标从0开始 ダブル DIS(CONST PII&S1、CONST PII&S2) { 戻り SQRT((s1.fi-s2.fi)*(s1.fi-s2.fi)+(s1.se -s2.se)*(s1.se- s2.se));PII&S2) { リターン((LL)s1.fi-s2.fi)*(s1.fi-s2.fi)+(s1.se-s2.se)*(s1.se- s2.se)。 } PIIの演算子 - (CONST PII&S1、CONST PII&S2) { 戻り MP(s1.fi-s2.fi、s1.se- s2.se)。 } INT S [MAXN]。// 栈 INT chaji(CONSTの PII&S1、CONSTの PII&S2)// 差积 { 戻り s1.fi * s2.se-s1.se * s2.fi。 } ブール COMP(CONST PII&S1、CONST PII&S2) { int型のx = chaji(S1-点[ 0 ]、S2点[ 0 ])。 もし(X> 0 ||(のx == 0 &&ファブ(s1.fi点[ 0 ] .fi)<ファブ(s2.fi点[ 0 ] .fi)))リターン 1 。 それ以外 の戻り 0 ; } 二重 sqare(CONST PIIと、CONST PII&B、CONST PII&C) { 戻り 0.5 * ABS((b.fi-a.fi)*(c.se-a.seを) - (c.fi - 。 FI)*(b.se- a.se)); } int型)(主 { :: sync_with_stdio IOSの(偽の); cout.tie(0 ); cin.tie(0 ); INT N-、CNT = 0 ; // 点のn個、cntが凸包の点の数である CIN >> N-、 REP (I、0、N-)>> CINポイント[I] .fi >> ポイント[I] .SE; IF(N - == 2 ) { COUT << powdis(ポイント[ 0 ]、ポイント[ 1 ])<< " \ N- " ; 戻り 0 ; } int型の P = 0 ; REP(I、1 、n)の 場合(点[i]が.SE <ポイント[P] || .SE(点[i]は.SE ==ポイント[P] .SE &&点[i]は.fi < ポイント[P] .fi)) P = I; スワップ(点[ 0 ]、ポイント[P])。 ソート(点 + 1、点+ N、COMP)。 S [CNT ++] = 0 ; S [CNT ++] = 1 。 担当者(I、2 、n)の { つつ > =(CNT 2 && chaji(点[S [CNT- 1 ] -点[i]は、点[S [CNT- 2 ] -点[I])> = 0)cnt-- ; S [CNT++] = I; } LL ANS = 0 。 P = 2 。 担当者(I、0 、CNT) { 一方(sqare(点[S [I]、点[S [(I + 1)%のCNT]、点[S [P])<sqare(点[S [I ]、点[S [(I + 1)%のCNT]、点[S [(P + 1)%のCNT])) P =(P + 1)%のCNT。 ANS = MAX(ANS、powdis(点[S [I]、点[S [P])); ANS = MAX(ANS、powdis(点[S [(I + 1)%のCNT]、点[S [P])); ANS= MAX(ANS、powdis(点[S [I]、点[S [(P + 1)%のCNT]]))。 ANS = MAX(ANS、powdis(点[S [(I + 1)%のCNT]、点[S [(P + 1)%のCNT]]))。 } COUT << ANS << ENDL。 リターン 0 ; }