$ O(N ^ 2)以下の条件を満足する共通部分の必要性の$列挙:
- 共通部分(コーナー、エッジの長さ、角度、エッジの長さ、コーナー、...)配列と同じです。
- そして、両端の角度が$ 180 $度を超えていません。
- 残りの角部(両方とも包括的には)$ 180 $度を超えていません。
(3)を直接列挙するとき、(1)及び(2)(1)ハッシュ、同じ角度$(B)のハッシュ値であってもよい$、$に置くて決定することができます最小値に並べ替え$、$およびメンテナンスB $ときのダブルポインタ。
時間複雑$ O(N ^ 2 \ログn)と$。
書式#include <cstdioを> 書式#include <cmath> 書式#include <アルゴリズム> 名前空間stdを使用。 ダブルLDのtypedef。 符号なしの長い長いLLのtypedef。 const int型N = 2010; CONST LD EPS = 1E-9、PI = ACOS(-1.0)。 インラインINT SGN(LD x)から{ IF(X> EPS)リターン1。 IF(X <-EPS)リターン-1。 0を返します。 } 整数N、M、CE、I、J、R [N]、CP; LDをF [N]、G [N]、H [N]、SL [N << 1]、SR [N << 1]。 LL VL [N << 1]、VR [N << 1]、P [N << 1]。 構造体P { LD X、Y。 P(){} P(LDの_x、LDの_y){X = _x、Y = _y;} P operator- CONST(P&B CONST){リターンP(xb.x、yb.y);} CONST(P&B CONST)LD演算子* {X * b.x + Y *によってリターン;} LDのLEN(){戻り関数hypot(X、Y);} ボイドリード(){scanf関数( "%LF%LF"、およびX&Y);} } [N]、B [N]。 構造体E { LL L; INT R、LD A、B。 E(){} E(LL _L、INT _r、LD _a、LD _b){L = _L、R = _r、A = _a、B = _b;} } E [2000005]。 構造体民{ LDのx、int型のp; A(){} NUM(LD _x、INT _p){X = _x、P = _P;} }プール[N << 2]。 構造体EV { LDのA、B; EV(){} EV(LDの_a、LDの_b){= _a、B = _b;} }エル[N]である[N]。 インラインBOOL CMP(NUM&CONST、民&B CONST){リターンAX <BX;} インラインBOOL CMPE(CONST E&、constのE&B){戻りら<BL;} インラインBOOL cmpev(CONST EV&、CONST EV&B){戻りAA <BA;} インラインLDクロス(P&、CONST P&B CONST){戻りAX *によって、AY * BX;} インラインボイドINITL(INT N、P *、LD * S){ 私は、jはint型。 LD領域= 0。 エリア+ =クロス([I]、[(I + 1)%N](); I <N I ++ I = 0)ため、 IF(領域<0)(+ n)を逆。 {(; I <N I ++ I = 0)するため Pプレ= [(I + N-1)%のn]は、SUF = A [(I + 1)%N]。 F [I] = ACOS((オン[I])*(SUF - [I])/(オン[I])。のみ()/(SUF - [I])。のみ() ); G [I] =クロス([I] -pre、SUF - [I])。 .LEN H [I] =([I] -suf)(); } ための式(I = 0; iが<= N + N; iが++){ (I> = N)F [I] = F [I%のN]、G [I] = G [I%N]であれば、 S [I << 1] = G [i]は、 S [I << 1 | 1] = H [I%N]。 } R [I] = SGN(G [I])> 0 R [I + 1? - (I; I〜R [N * 2 + 1] = N * 2 + 1、i = N * 2)のために]:I-1。 ための式(I = 0; iが<N; I ++)IF(SGN(G [I])> 0)(J = I + N-1; J> I; Jは、 - )IF(SGN(G [J] )> 0){ IF(R [J + 1] <I + N-1)ブレーク。 E [++ CE] = E( - (I << 1 | 1)、(J << 1)-1、F [i]は、F [J])。 } } インラインボイドINITR(INT N、P *、LD * S){ 私は、jはint型。 LD領域= 0。 エリア+ =クロス([I]、[(I + 1)%N](); I <N I ++ I = 0)ため、 IF(領域> 0)(+ n)を逆。 {(; I <N I ++ I = 0)するため Pプレ= [(I + N-1)%のn]は、SUF = A [(I + 1)%N]。 F [I] = ACOS((オン[I])*(SUF - [I])/(オン[I])。のみ()/(SUF - [I])。のみ() ); G [I] =クロス([I] -pre、SUF - [I])。 .LEN H [I] =([I] -suf)(); } ための式(I = 0; iが<= N + N; iが++){ (I> = N)F [I] = F [I%のN]、G [I] = G [I%N]であれば、 S [I << 1] = G [i]は、 S [I << 1 | 1] = H [I%N]。 } R [I] = SGN(G [i])と<0 R [I + 1? - (I;〜iはR [N * 2 + 1] = N * 2 + 1、i = N * 2)のために]:I-1。 (SGN(G [i]の場合 - (SGN(G [i])と<0)であれば(J J = I + N-1; J> i)に対する(I ++; I <N I = 0)するため)<0){ IF(R [J + 1] <I + N-1)ブレーク。 E [++ CE] = E(I << 1 | 1、(J << 1)-1、F [i]は、F [J])。 } } インラインBOOLチェック(INT nは、INT M){ (!N ||メートル)であれば、戻り0; ソート(1 + + N + 1 cmpev)。 黒(+ 1、+のM + 1、cmpevです)。 int型I、J、LDのT = 100; { - (I; I iは= N、J = 1)のために 一方、(j <= M && SGN(EL [I] .A + ER [J] .A-PI)<= 0)T =分(T、ER [J ++] B。)。 IF(SGN(EL [I] .B + T-PI)<= 0)リターン1。 } 0を返します。 } インライン{)(解くBOOL INT I、J、K、L、R。 CP = 0; 以下のために(私は= 0; iが<= N * 4 + 1; I ++)プール[CP ++] =民(SL [i]は、I << 1)。 プール[CP ++] =民(SR [i]は、I << 1 | 1)は、(i ++; I <= M * 4 + 1 I = 0)ため、 ソート(プール、プール+ CP、CMP); LL RAN = 998244353; {(; I <CP iがjは= I = 0)するため (; J <CP &&はsgn(プール[I] .X-プール[J] .X);!J ++、J = i)に対する; (; K <J; K ++、K = I)の場合(プール[K] .P&1)VR [プール[] .P kは>> 1] = RAN;のための他のVL [プール[K] .P >> 1] = RAN; ran=ran*1000000007+13331; } VL [I] + = VL [I-1] * 233(I ++; I <= N * 4 + 1 I = 1の)のため; ための式(I = 1; I <= M * 4 + 1; I ++)VR [I] + = VR [I-1] * 233。 ためた(p [0] = I 1 =、iが<= M * 4 + 1 || I <= N * 4 + 1; I ++)P [I] = P [I-1] * 233。 用(; I <= CE; iが1 = I ++){ L = E [I] .L、R = E [I] .R。 IF(L <0){ [あなた] .L = VL [R] -VL [-L-1] * P [R + L + 1]。 E [I]。R = 0。 }そうしないと{ E [I]【選択= VR [R] -VR [1] * P [L + 1]。 E [I]。R = 1。 } } ソート(S + 1、S + + 1、CMPEなど); {(; I <= CE iがjは= I = 1の)のために 用(J = I; J <= CE && E [I] .L == E [J] .L; J ++)。 int型、CL = 0、CR = 0; 用(K = I、K <J、K ++)IF(E [K]・R)ER [++ CR] = EV(E .A [K]、E [k]は.B);他のEL [++ CL = EV(E [K] .A、E [k]は.B)。 もし(チェック(CL、CR))リターン1。 } 0を返します。 } INTメイン(){ 一方、(〜のscanf( "%d個"、&N)){ [I] .read()は、(i ++; I <N I = 0)ため、 scanf関数( "%のD"、&M)。 B [i]が.read();(; I <M I ++ I = 0)するため {(; I <2 I ++ I = 0)するため それは= 0; INITL(N、SL)。 INITR(M、B、SR)。 {()(解く)場合 プット( "1"); ブレーク; } スワップ(N、M)。 (; J <N || J <M、J ++ J = 0)、スワップ([J]、B [J])のために、 } もし(I == 2)プット( "0"); } 0を返します。 }