BZOJ2191:スプリット

$ O(N ^ 2)以下の条件を満足する共通部分の必要性の$列挙:

  1. 共通部分(コーナー、エッジの長さ、角度、エッジの長さ、コーナー、...)配列と同じです。
  2. そして、両端の角度が$ 180 $度を超えていません。
  3. 残りの角部(両方とも包括的には)$ 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を返します。
}

  

おすすめ

転載: www.cnblogs.com/clrs97/p/12204007.html