zoukankan      html  css  js  c++  java
  • BZOJ 4698: Sdoi2008 Sandy的卡片

    4698: Sdoi2008 Sandy的卡片

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 106  Solved: 40
    [Submit][Status][Discuss]

    Description

    Sandy和Sue的热衷于收集干脆面中的卡片。然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型。每一张卡片都由一些数字进行标记,第i张卡片的序列长度为Mi,要想兑换人物模型,首先必须要集够N张卡片,对于这N张卡片,如果他们都有一个相同的子串长度为k,则可以兑换一个等级为k的人物模型。相同的定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串。Sandy的卡片数远远小于要求的N,于是Sue决定在Sandy的生日将自己的卡片送给Sandy,在Sue的帮助下,Sandy终于集够了N张卡片,但是,Sandy并不清楚他可以兑换到哪个等级的人物模型,现在,请你帮助Sandy和Sue,看看他们最高能够得到哪个等级的人物模型。

    Input

    第一行为一个数N,表示可以兑换人物模型最少需要的卡片数,即Sandy现在有的卡片数.
    第i+1行到第i+N行每行第一个数为第i张卡片序列的长度Mi,之后j+1到j+1+Mi个数,用空格分隔,分别表示序列中.
    的第j个数.
    n<=1000,M<=1000,2<=Mi<=101

    Output

    一个数k,表示可以获得的最高等级。
     

    Sample Input

    2
    2 1 2
    3 4 5 9

    Sample Output

    2

    HINT

    Source

    [Submit][Status][Discuss]

    首先,对于题目中的匹配,可以转换成两个相邻数字之间差值的匹配问题。因此对于每个数字串,先前后做差得到新的数字串,然后把N个新串连起来求后缀数组。二分答案,在后缀数组中找出所有联系的height值>=k的区间,判断是否能满足存在N个在不同串中开始的后缀,如果能,就是一个合法的k。

    调了好久都不对,满脸黑线,一怒之下打开Vim,参考hzwer的代码,没加tab就一A了。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define N 1005
     4 #define M 1000005
     5 int n,mn=2e9,mx=0,lt,rt=2e9,mid,ans=1;
     6 int a[N][N],l[N],b[M],id[M],tot,vis[N],cnt;
     7 int sa[M],ta[M],rk[M],ht[M],wa[M],wb[M],ca[M],cb[M];
     8 inline bool check(int k)
     9 {
    10   for(int i=1;i<=tot;++i)
    11   {
    12     if(ht[i]<k)memset(vis,0,sizeof(vis)),cnt=0;
    13     if(!vis[id[sa[i]]])vis[id[sa[i]]]=1,++cnt;
    14     if(cnt==n)return true;
    15   }
    16   return false;
    17 }
    18 signed main(void)
    19 {
    20   scanf("%d",&n);
    21   for(int i=1;i<=n;++i)
    22   {
    23     scanf("%d",l+i);
    24     for(int j=1;j<=l[i];++j)
    25     {
    26       scanf("%d",&a[i][j]);
    27       if(j>1)mx=max(mx,a[i][j]-a[i][j-1]);
    28     }
    29     rt=min(rt,l[i]);
    30   }
    31   for(int i=1;i<=n;++i)
    32   {
    33     for(int j=2;j<=l[i];++j)b[++tot]=a[i][j]-a[i][j-1],id[tot]=i;
    34     b[++tot]=++mx;
    35   }
    36   for(int i=1;i<=tot;++i)mn=min(mn,b[i]);
    37   for(int i=1;i<=tot;++i)b[i]=b[i]-mn+1,mx=max(mx,b[i]);
    38   memset(ca,0,sizeof(ca));
    39   for(int i=1;i<=tot;++i)++ca[b[i]];
    40   for(int i=1;i<=mx;++i)ca[i]+=ca[i-1];
    41   for(int i=tot;i>=1;--i)sa[ca[b[i]]--]=i;
    42   rk[sa[1]]=1;
    43   for(int i=2;i<=tot;++i)rk[sa[i]]=rk[sa[i-1]]+(b[sa[i]]!=b[sa[i-1]]);
    44   for(int k=1;rk[sa[tot]]<tot;k<<=1)
    45   {
    46     memset(ca,0,sizeof(ca));
    47     memset(cb,0,sizeof(cb));
    48     for(int i=1;i<=tot;++i)++ca[wa[i]=rk[i]],++cb[wb[i]=i+k<=tot?rk[i+k]:0];
    49     for(int i=1;i<=tot;++i)ca[i]+=ca[i-1],cb[i]+=cb[i-1];
    50     for(int i=tot;i>=1;--i)ta[cb[wb[i]]--]=i;
    51     for(int i=tot;i>=1;--i)sa[ca[wa[ta[i]]]--]=ta[i];
    52     rk[sa[1]]=1;
    53     for(int i=2;i<=tot;++i)rk[sa[i]]=rk[sa[i-1]]+(wa[sa[i]]!=wa[sa[i-1]]||wb[sa[i]]!=wb[sa[i-1]]);
    54   }
    55   for(int i=1,j=0;i<=tot;++i)
    56   {
    57     if(--j<0)j=0;
    58     while(b[i+j]==b[sa[rk[i]-1]+j])++j;
    59     ht[rk[i]]=j;
    60   }
    61   while(lt<=rt)
    62   {
    63     if(check(mid=(lt+rt)>>1))
    64       ans=mid+1,lt=mid+1;
    65     else rt=mid-1;
    66   }
    67   printf("%d
    ",ans);
    68 }

    2017.01.13 补加Tab

    @Author: YouSiki

  • 相关阅读:
    大数据方向招人难啊!!
    .netcore 急速接入第三方登录,不看后悔
    T-SQL——函数——时间操作函数
    T-SQL——关于XML类型
    机器学习方法
    可读性友好的JavaScript:两个专家的故事
    快速了解 JavaScript ES2019 的五个新增特性
    了解 Vue 的 Compsition API
    使用 JavaScript 操作浏览器历史记录 API
    JavaScript ES 模块:现代化前端编程必备技能
  • 原文地址:https://www.cnblogs.com/yousiki/p/6210982.html
Copyright © 2011-2022 走看看