zoukankan      html  css  js  c++  java
  • BZOJ1039 : [ZJOI2008]无序运动Movement

    首先不考虑翻转,对于两个等长的序列,如果任意两条相邻边的边长比以及夹角都相等,那么就匹配。

    为了避免实数运算,边长比可以上下平方,然后约分。夹角可以用叉积和点积的最简比值来表示,注意上下符号都要保留。

    然后将这些信息离散化,转化成数字串匹配问题,建出用Hash表存边的AC自动机后即可解决。

    对于翻转,可以考虑将匹配串翻转,然后再做一次,累加答案,注意特判某些翻转后和原串相等的串。

    #include<cstdio>
    #include<algorithm>
    const int N=200010,M=1600010,U=4194303;
    int n,m,i,j,k,x,y,en,flag,len[M],l[M],ans[M];bool one[M];
    struct P{
      int x,y;
      P(){}
      P(int _x,int _y){x=_x,y=_y;}
      P operator-(const P&b){return P(x-b.x,y-b.y);}
      int len(){return x*x+y*y;}
      int operator*(const P&b){return x*b.y-y*b.x;}
      int operator^(const P&b){return x*b.x+y*b.y;}
    }a[N],A,B;
    int b[N],c[N];
    inline int sig(int x){return x>0?1:-1;}
    inline int abs(int x){return x>0?x:-x;}
    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    struct Num{
      int a,b,c,d;
      Num(){}
      Num(int A,int B,int C,int D){
        int g=gcd(A,B);
        a=A/g,b=B/g;
        if(!C)c=0,d=sig(D);
        else if(!D)c=sig(C),d=0;
        else{
          g=gcd(abs(C),abs(D));
          c=C/g,d=D/g;
        }
      }
      bool operator<=(const Num&x){
        if(a!=x.a)return a<x.a;
        if(b!=x.b)return b<x.b;
        if(c!=x.c)return c<x.c;
        return d<=x.d;
      }
      bool operator!=(const Num&x){
        if(a!=x.a)return 1;
        if(b!=x.b)return 1;
        if(c!=x.c)return 1;
        return d!=x.d;
      }
    }pool[M];
    int cnt,all[M];
    inline int cmp(int a,int b){
      Num*A=pool+a,*B=pool+b;
      if(A->a!=B->a)return A->a<B->a;
      if(A->b!=B->b)return A->b<B->b;
      if(A->c!=B->c)return A->c<B->c;
      return A->d<B->d;
    }
    inline int getid(const Num&x){
      int l=1,r=cnt,mid,t=0;
      while(l<=r)if(pool[all[mid=(l+r)>>1]]<=x)l=(t=mid)+1;else r=mid-1;
      if(!t)return 0;
      if(pool[all[t]]!=x)return 0;
      return t;
    }
    inline void read(int&a){
      char c;bool f=0;a=0;
      while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
      if(c!='-')a=c-'0';else f=1;
      while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
      if(f)a=-a;
    }
    int tot,f[M],q[M],tag[M];
    int g[U+1],G[M],ed;
    struct E{int x,y,z,nxt;E(){}E(int _x,int _y,int _z,int _nxt){x=_x,y=_y,z=_z,nxt=_nxt;}}e[M];
    struct S{int y,z,nxt;S(){}S(int _y,int _z,int _nxt){y=_y,z=_z,nxt=_nxt;}}s[M];
    inline int son(int x,int y){
      int u=(x<<8|y)&U;
      for(int p=g[u];p;p=e[p].nxt)if(e[p].x==x&&e[p].y==y)return e[p].z;
      e[++ed]=E(x,y,++tot,g[u]);g[u]=ed;
      s[ed]=S(y,tot,G[x]);G[x]=ed;
      return tot;
    }
    inline int ask(int x,int y){
      int u=(x<<8|y)&U;
      for(int p=g[u];p;p=e[p].nxt)if(e[p].x==x&&e[p].y==y)return e[p].z;
      return 0;
    }
    void make(){
      int h=0,t=0,i,j,x,y,z;f[0]=-1;
      while(h<=t)for(i=G[x=q[h++]];i;i=s[i].nxt){
        y=s[i].y,q[++t]=z=s[i].z;
        if(x)for(j=f[x];~j;j=f[j])if(k=ask(j,y)){f[z]=k;break;}
      }
    }
    int main(){
      read(n),read(m);
      for(i=1;i<=m;i++){
        read(k);len[i]=k;
        for(j=1;j<=k;j++)read(a[j].x),read(a[j].y);
        if(k<=2)continue;
        l[i]=cnt+1;
        for(flag=1,j=2;j<k;j++){
          A=a[j]-a[j-1],B=a[j+1]-a[j];
          pool[++cnt]=Num(A.len(),B.len(),A*B,A^B);
          if(A*B)flag=0;
        }
        if(flag)one[i]=1;
      }
      for(i=1;i<=cnt;i++)all[i]=i;
      if(cnt>1)std::sort(all+1,all+cnt+1,cmp);
      for(i=1;i<=n;i++)read(a[i].x),read(a[i].y);
      for(i=2;i<n;i++){
        A=a[i]-a[i-1],B=a[i+1]-a[i];
        b[i]=getid(Num(A.len(),B.len(),A*B,A^B));
        c[i]=getid(Num(A.len(),B.len(),-(A*B),A^B));
      }
      for(i=1;i<=m;i++)if(l[i]){
        en=l[i]+len[i]-2;
        for(x=0,j=l[i];j<en;j++)x=son(x,getid(pool[j]));
        l[i]=x;
      }
      make();
      for(x=0,i=2;i<n;i++){
        while(x&&!ask(x,b[i]))x=f[x];
        tag[x=ask(x,b[i])]++;
      }
      for(i=tot;i;i--)tag[f[q[i]]]+=tag[q[i]];
      for(i=1;i<=m;i++)if(l[i])ans[i]+=tag[l[i]];
      for(i=0;i<=tot;i++)tag[i]=0;
      for(x=0,i=2;i<n;i++){
        while(x&&!ask(x,c[i]))x=f[x];
        tag[x=ask(x,c[i])]++;
      }
      for(i=tot;i;i--)tag[f[q[i]]]+=tag[q[i]];
      for(i=1;i<=m;i++)if(l[i]&&!one[i])ans[i]+=tag[l[i]];
      for(i=1;i<=m;i++)if(!l[i])printf("%d
    ",n-len[i]+1);else printf("%d
    ",ans[i]);
      return 0;
    }
    

      

  • 相关阅读:
    深入理解JavaScript定时器(续)
    也谈前端基础设施建设
    Reporting Services在指定计算机上找不到报表服务器
    优化tempdb提高SQL Server的性能
    SQL 代理服务未运行。此操作需要 SQL 代理服务。 (rsSchedulerNotResponding) 获取联机帮助
    报表服务器上出现内部错误。有关详细信息,请参阅错误日志。 (rsInternalError) 获取联机帮助.找不到存储过程 'GetOneConfigurationInfo'。
    表中包含有外键时无法进行导入数据,
    SQLSTATE ODBC API(驱动程序管理器)错误
    数据库只能用机器名连接,不能用ip地址连接
    请教:不能访问通过IP访问,却可以通过机器名访问
  • 原文地址:https://www.cnblogs.com/clrs97/p/5019130.html
Copyright © 2011-2022 走看看