zoukankan      html  css  js  c++  java
  • BZOJ3873 : [Ahoi2014]拼图

    如果答案在某个碎片内部,那么直接悬线法解决,时间复杂度$O(nsum)$。

    如果$n$比较大,那么$sum$比较小。

    求出每个点向上能延伸的长度,枚举每个点向上这条线段作为短板。

    算出完全可选的碎片的长度之和以及不能完全选,左边右边最大次大延伸距离,更新答案。

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

    如果$n$比较小,那么暴力枚举上下边界,计算答案方法同上。

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

    总时间复杂度$O(nsumsqrt{nsum})$。

    #include<cstdio>
    const int N=100010,M=320;
    int T,num,n,m,i,j,k,x,cnt,FL0,GL,FL1,FR0,GR,FR1,ans;
    inline void up(int&f0,int&g0,int&f1,int x,int y){
      if(x>f0){f1=f0,f0=x,g0=y;return;}
      if(x>f1)f1=x;
    }
    inline void uans(int x){if(ans<x)ans=x;}
    namespace NSMALL{
    int st[N],en[N],f[N],g[N],w[N];char a[M][N],s[N];
    void solve(){
      for(i=1;i<=num;i++){
        scanf("%d",&x);
        st[i]=m+1;
        en[i]=m+x;
        for(j=1;j<=n;j++){
          scanf("%s",s);
          for(k=0;k<x;k++)a[j][k+st[i]]=s[k]-'0';
        }
        m+=x;
      }
      for(i=1;i<=m;i++)f[i]=1,g[i]=m,w[i]=0;
      for(i=1;i<=n;i++){
        for(GL=j=1;j<=m;j++)if(!a[i][j]){
          w[j]++;
          if(GL>f[j])f[j]=GL;
        }else w[j]=0,f[j]=1,g[j]=m,GL=j+1;
        for(GR=j=m;j;j--)if(!a[i][j]){
          if(GR<g[j])g[j]=GR;
          uans(w[j]*(g[j]-f[j]+1));
        }else GR=j-1;
      }
      for(i=1;i<=n;i++){
        for(k=1;k<=num;k++)f[k]=en[k],g[k]=st[k];
        for(j=i;j<=n;j++){
          cnt=FL0=GL=FL1=FR0=GR=FR1=0;
          for(k=1;k<=num;k++){
            for(x=st[k];x<=en[k];x++)if(a[j][x])break;
            if(f[k]>x-1)f[k]=x-1;
            for(x=en[k];x>=st[k];x--)if(a[j][x])break;
            if(g[k]<x+1)g[k]=x+1;
            if(f[k]==en[k]){cnt+=en[k]-st[k]+1;continue;}
            up(FL0,GL,FL1,f[k]-st[k]+1,k);
            up(FR0,GR,FR1,en[k]-g[k]+1,k);
          }
          if(GL!=GR)uans((j-i+1)*(cnt+FL0+FR0));else{
            uans((j-i+1)*(cnt+FL0+FR1));
            uans((j-i+1)*(cnt+FL1+FR0));
          }
        }
      }
    }
    }
    namespace NBIG{
    int st[M],en[M],f[M],g[M],w[M];char a[N][M],s[M];
    void solve(){
      for(i=1;i<=num;i++){
        scanf("%d",&x);
        st[i]=m+1;
        en[i]=m+x;
        for(j=1;j<=n;j++){
          scanf("%s",s);
          for(k=0;k<x;k++)a[j][k+st[i]]=s[k]-'0';
        }
        m+=x;
      }
      for(i=1;i<=m;i++)f[i]=1,g[i]=m,w[i]=0;
      for(i=1;i<=n;i++){
        for(GL=j=1;j<=m;j++)if(!a[i][j]){
          w[j]++;
          if(GL>f[j])f[j]=GL;
        }else w[j]=0,f[j]=1,g[j]=m,GL=j+1;
        for(GR=j=m;j;j--)if(!a[i][j]){
          if(GR<g[j])g[j]=GR;
          uans(w[j]*(g[j]-f[j]+1));
        }else GR=j-1;
      }
      for(i=1;i<=m;i++)w[i]=0;
      for(i=1;i<=n;i++){
        for(j=1;j<=m;j++)if(a[i][j])w[j]=0;else w[j]++;
        for(j=1;j<=m;j++)if(w[j]){
          cnt=FL0=GL=FL1=FR0=GR=FR1=0;
          for(k=1;k<=num;k++){
            for(x=st[k];x<=en[k];x++)if(w[x]<w[j])break;
            f[k]=x-1;
            for(x=en[k];x>=st[k];x--)if(w[x]<w[j])break;
            g[k]=x+1;
            if(f[k]==en[k]){cnt+=en[k]-st[k]+1;continue;}
            up(FL0,GL,FL1,f[k]-st[k]+1,k);
            up(FR0,GR,FR1,en[k]-g[k]+1,k);
          }
          if(GL!=GR)uans(w[j]*(cnt+FL0+FR0));else{
            uans(w[j]*(cnt+FL0+FR1));
            uans(w[j]*(cnt+FL1+FR0));
          }
        }
      }
    }
    }
    int main(){
      scanf("%d",&T);
      while(T--){
        scanf("%d%d",&num,&n);
        m=ans=0;
        if(n<=315)NSMALL::solve();else NBIG::solve();
        printf("%d
    ",ans);
      }
      return 0;
    }
    

      

  • 相关阅读:
    第13章 使用ADO.NET访问数据库
    第11章 连接查询和分组查询
    第10章 模糊查询和聚合函数
    第9章 数据查询基础
    数据库前三章测试题
    用表组织数据
    程序数据集散地:数据库
    深入C#的String类
    线程池
    hadoop-2.8.0 完全分布式运行模式
  • 原文地址:https://www.cnblogs.com/clrs97/p/5617207.html
Copyright © 2011-2022 走看看