zoukankan      html  css  js  c++  java
  • BZOJ2191 : Split

    $O(n^2)$枚举公共部分,需要满足以下条件:

    1. 公共部分的(转角,边长,转角,边长,转角,...)序列相等。
    2. 两端的角度之和都不超过$180$°。
    3. 剩下部分(包括两端)的角度不超过$180$°。

    (3)可以直接在枚举的时候判断掉,对于(1)和(2),可以将(1)哈希,对于哈希值相同的角度对$(a,b)$,将它们按照$a$排序,然后在双指针时维护$b$的最小值即可。

    时间复杂度$O(n^2log n)$。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef double ld;
    typedef unsigned long long ll;
    const int N=2010;
    const ld eps=1e-9,pi=acos(-1.0);
    inline int sgn(ld x){
      if(x>eps)return 1;
      if(x<-eps)return -1;
      return 0;
    }
    int 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];
    struct P{
      ld x,y;
      P(){}
      P(ld _x,ld _y){x=_x,y=_y;}
      P operator-(const P&b)const{return P(x-b.x,y-b.y);}
      ld operator*(const P&b)const{return x*b.x+y*b.y;}
      ld len(){return hypot(x,y);}
      void read(){scanf("%lf%lf",&x,&y);}
    }a[N],b[N];
    struct 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];
    struct Num{
      ld x;int p;
      Num(){}
      Num(ld _x,int _p){x=_x,p=_p;}
    }pool[N<<2];
    struct EV{
      ld a,b;
      EV(){}
      EV(ld _a,ld _b){a=_a,b=_b;}
    }el[N],er[N];
    inline bool cmp(const Num&a,const Num&b){return a.x<b.x;}
    inline bool cmpe(const E&a,const E&b){return a.l<b.l;}
    inline bool cmpev(const EV&a,const EV&b){return a.a<b.a;}
    inline ld cross(const P&a,const P&b){return a.x*b.y-a.y*b.x;}
    inline void initl(int n,P*a,ld*s){
      int i,j;
      ld area=0;
      for(i=0;i<n;i++)area+=cross(a[i],a[(i+1)%n]);
      if(area<0)reverse(a,a+n);
      for(i=0;i<n;i++){
        P pre=a[(i+n-1)%n],suf=a[(i+1)%n];
        f[i]=acos((pre-a[i])*(suf-a[i])/(pre-a[i]).len()/(suf-a[i]).len());
        g[i]=cross(a[i]-pre,suf-a[i]);
        h[i]=(a[i]-suf).len();
      }
      for(i=0;i<=n+n;i++){
        if(i>=n)f[i]=f[i%n],g[i]=g[i%n];
        s[i<<1]=g[i];
        s[i<<1|1]=h[i%n];
      }
      for(r[n*2+1]=n*2+1,i=n*2;~i;i--)r[i]=sgn(g[i])>0?r[i+1]:i-1;
      for(i=0;i<n;i++)if(sgn(g[i])>0)for(j=i+n-1;j>i;j--)if(sgn(g[j])>0){
        if(r[j+1]<i+n-1)break;
        e[++ce]=E(-(i<<1|1),(j<<1)-1,f[i],f[j]);
      }
    }
    inline void initr(int n,P*a,ld*s){
      int i,j;
      ld area=0;
      for(i=0;i<n;i++)area+=cross(a[i],a[(i+1)%n]);
      if(area>0)reverse(a,a+n);
      for(i=0;i<n;i++){
        P pre=a[(i+n-1)%n],suf=a[(i+1)%n];
        f[i]=acos((pre-a[i])*(suf-a[i])/(pre-a[i]).len()/(suf-a[i]).len());
        g[i]=cross(a[i]-pre,suf-a[i]);
        h[i]=(a[i]-suf).len();
      }
      for(i=0;i<=n+n;i++){
        if(i>=n)f[i]=f[i%n],g[i]=g[i%n];
        s[i<<1]=g[i];
        s[i<<1|1]=h[i%n];
      }
      for(r[n*2+1]=n*2+1,i=n*2;~i;i--)r[i]=sgn(g[i])<0?r[i+1]:i-1;
      for(i=0;i<n;i++)if(sgn(g[i])<0)for(j=i+n-1;j>i;j--)if(sgn(g[i])<0){
        if(r[j+1]<i+n-1)break;
        e[++ce]=E(i<<1|1,(j<<1)-1,f[i],f[j]);
      }
    }
    inline bool check(int n,int m){
      if(!n||!m)return 0;
      sort(el+1,el+n+1,cmpev);
      sort(er+1,er+m+1,cmpev);
      int i,j;ld t=100;
      for(i=n,j=1;i;i--){
        while(j<=m&&sgn(el[i].a+er[j].a-pi)<=0)t=min(t,er[j++].b);
        if(sgn(el[i].b+t-pi)<=0)return 1;
      }
      return 0;
    }
    inline bool solve(){
      int i,j,k,l,r;
      cp=0;
      for(i=0;i<=n*4+1;i++)pool[cp++]=Num(sl[i],i<<1);
      for(i=0;i<=m*4+1;i++)pool[cp++]=Num(sr[i],i<<1|1);
      sort(pool,pool+cp,cmp);
      ll ran=998244353;
      for(i=0;i<cp;i=j){
        for(j=i;j<cp&&!sgn(pool[i].x-pool[j].x);j++);
        for(k=i;k<j;k++)if(pool[k].p&1)vr[pool[k].p>>1]=ran;else vl[pool[k].p>>1]=ran;
        ran=ran*1000000007+13331;
      }
      for(i=1;i<=n*4+1;i++)vl[i]+=vl[i-1]*233;
      for(i=1;i<=m*4+1;i++)vr[i]+=vr[i-1]*233;
      for(p[0]=i=1;i<=m*4+1||i<=n*4+1;i++)p[i]=p[i-1]*233;
      for(i=1;i<=ce;i++){
        l=e[i].l,r=e[i].r;
        if(l<0){
          e[i].l=vl[r]-vl[-l-1]*p[r+l+1];
          e[i].r=0;
        }else{
          e[i].l=vr[r]-vr[l-1]*p[r-l+1];
          e[i].r=1;
        }
      }
      sort(e+1,e+ce+1,cmpe);
      for(i=1;i<=ce;i=j){
        for(j=i;j<=ce&&e[i].l==e[j].l;j++);
        int cl=0,cr=0;
        for(k=i;k<j;k++)if(e[k].r)er[++cr]=EV(e[k].a,e[k].b);else el[++cl]=EV(e[k].a,e[k].b);
        if(check(cl,cr))return 1;
      }
      return 0;
    }
    int main(){
      while(~scanf("%d",&n)){
        for(i=0;i<n;i++)a[i].read();
        scanf("%d",&m);
        for(i=0;i<m;i++)b[i].read();
        for(i=0;i<2;i++){
          ce=0;
          initl(n,a,sl);
          initr(m,b,sr);
          if(solve()){
            puts("1");
            break;
          }
          swap(n,m);
          for(j=0;j<n||j<m;j++)swap(a[j],b[j]);
        }
        if(i==2)puts("0");
      }
      return 0;
    }
    

      

  • 相关阅读:
    数据结构 trie 树 入门练手 POJ 3630 Phone List
    回溯法求 1~n 的排列
    POJ 1988 Cube Stacking (并查集,节点到根节点的距离题目)
    Ubuntu下的截图软件
    git使用方法
    在Linux下安装ADT
    在Linux下安装Android SDK
    在Linux下安装Java JDK
    研发项目风险因素差异性
    关于C#的partial修饰符
  • 原文地址:https://www.cnblogs.com/clrs97/p/12204007.html
Copyright © 2011-2022 走看看