• 「luogu2463」[SDOI2008]Sandy的卡片


    获得原数列的差分数列,离散化后接在一起,中间用没有出现过的数分隔,于是问题就转化成求这个数列的最长重复子串,且每一段上都至少有一个子串。

    求出后缀数组,二分答案即可。

     1 #include<bits/stdc++.h>
     2 #define R register
     3 using namespace std;
     4 const int N=1010,M=1000010,oo=2e9;
     5 int n,m,tot,s[M],a[M],numpos[M];
     6 int x[M<<1],y[M<<1],sa[M<<1],rank[M],h[M],height[M],cnt[M],bel[M];
     7 int cmp(const int xx,const int yy){return a[xx]<a[yy];}
     8 void build(){
     9     for(R int i=1;i<=n;i++) cnt[x[i]]++;
    10     for(R int i=2;i<=m;i++) cnt[i]+=cnt[i-1];
    11     for(R int i=n;i;i--) sa[cnt[x[i]]--]=i;
    12     for(R int i=1;i<=m;i++) cnt[i]=0;
    13     for(R int k=1;k<=n;k<<=1){
    14         int num=0;
    15         for(R int i=n;i>n-k;i--) y[++num]=i;
    16         for(R int i=1;i<=n;i++) if(sa[i]>k) y[++num]=sa[i]-k;
    17         for(R int i=1;i<=n;i++) cnt[x[i]]++;
    18         for(R int i=2;i<=m;i++) cnt[i]+=cnt[i-1];
    19         for(R int i=n;i;i--) sa[cnt[x[y[i]]]--]=y[i];
    20         for(R int i=1;i<=m;i++) cnt[i]=0;
    21         swap(x,y);
    22         x[sa[1]]=num=1;
    23         for(R int i=2;i<=n;i++){
    24             if(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) num++;
    25             x[sa[i]]=num;
    26         }
    27         if(num>=n) break;
    28         m=num;
    29     }
    30     for(R int i=1;i<=n;i++) rank[sa[i]]=i;
    31     int t=0;
    32     for(R int i=1;i<=n;i++){
    33         if(t) t--;
    34         while(rank[i]-1&&s[i+t]==s[sa[rank[i]-1]+t]) t++;
    35         h[i]=t,height[rank[i]]=t;
    36     }
    37 }
    38 bool vis[N];
    39 bool check(int k){
    40     memset(vis,0,sizeof(vis));
    41     vis[0]=1;
    42     int minh=oo,cc=0;
    43     for(int i=1;i<=n;i++){
    44         minh=min(minh,height[i]);
    45         if(minh<k){
    46             memset(vis,0,sizeof(vis));
    47             vis[0]=1;
    48             cc=0,minh=oo;
    49         }else{
    50             if(!vis[bel[sa[i]]]) vis[bel[sa[i]]]=1,cc++;
    51             if(i>=1&&!vis[bel[sa[i-1]]]) vis[bel[sa[i-1]]]=1,cc++;
    52             if(cc>=tot) return 1;
    53         }
    54     }
    55     return 0;
    56 }
    57 int main(){
    58     int t1,t2,t3,div=1000000000;
    59     scanf("%d",&tot);
    60     for(R int i=1;i<=tot;i++){
    61         scanf("%d%d",&t1,&t2);
    62         for(int j=1;j<t1;j++) scanf("%d",&t3),a[++n]=t3-t2,x[n]=a[n],t2=t3,bel[n]=i,numpos[n]=n;
    63         a[++n]=++div,numpos[n]=n;
    64     }
    65     sort(numpos+1,numpos+n+1,cmp);
    66     int temp=0;
    67     x[numpos[1]]=s[numpos[1]]=++temp;
    68     for(int i=2;i<=n;i++){
    69         if(a[numpos[i]]!=a[numpos[i-1]]) temp++;
    70         s[numpos[i]]=x[numpos[i]]=temp;
    71     }
    72     m=temp;    
    73     build();
    74     int l=0,r=n,ans=0;
    75     while(l<=r){
    76         int mid=(l+r)>>1;
    77         if(check(mid)) l=mid+1,ans=mid;
    78         else r=mid-1;
    79     }
    80     printf("%d",ans+1);
    81     return 0;
    82 }
  • 相关阅读:
    tomcat启动Publishing failed with multiple errors
    oracle中merge into用法解析
    ORACLE数据库导出表,字段名,长度,类型,字段注释,表注释语句
    orcale的to_number方法
    Git删除无效远程分支
    .net core文件系统简介
    PowerShell的一些资料整理
    Jetbrains推出了一款新的编程字体Mono
    .net core程序强制以管理员权限启动
    在Asp.net Razor Pages/MVC程序中集成Blazor
  • 原文地址:https://www.cnblogs.com/mycups/p/8560121.html
Copyright © 2020-2023  润新知