zoukankan      html  css  js  c++  java
  • bzoj4199: [Noi2015]品酒大会

    题面见http://uoj.ac/problem/131

    一道后缀数组题

    先求出height,然后从大到小枚举每个height。

    然后对于每个height值,两端的集合中任意一对后缀的LCP都是这个height。

    我们统计答案之后合并两端的集合,用并查集维护即可。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define maxn 300005
     7 #define inf 1LL<<62
     8 using namespace std;
     9 typedef long long int64;
    10 char ch,s[maxn];
    11 int n,val[maxn];
    12 int64 ans[2][maxn];
    13 int fa[maxn],siz[maxn],list[maxn],max_val[maxn],min_val[maxn];
    14 int SA[maxn],rank[maxn],height[maxn],sum[maxn],t1[maxn],t2[maxn];
    15 bool cmp(int x,int y){
    16     if (height[x]!=height[y]) return height[x]>height[y];
    17     return x<y;
    18 }
    19 bool ok;
    20 void read(int &x){
    21     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    22     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    23     if (ok) x=-x;
    24 }
    25 void get_SA(){
    26     int *x=t1,*y=t2,m=255,tot=0;
    27     for (int i=1;i<=n;i++) sum[x[i]=s[i]]++;
    28     for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
    29     for (int i=n;i>=1;i--) SA[sum[x[i]]--]=i;
    30     for (int len=1;tot<n;len<<=1,m=tot){
    31         tot=0;
    32         for (int i=n-len+1;i<=n;i++) y[++tot]=i;
    33         for (int i=1;i<=n;i++) if (SA[i]>len) y[++tot]=SA[i]-len;    
    34         for (int i=1;i<=m;i++) sum[i]=0;
    35         for (int i=1;i<=n;i++) sum[x[y[i]]]++;
    36         for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
    37         for (int i=n;i>=1;i--) SA[sum[x[y[i]]]--]=y[i];
    38         swap(x,y),x[SA[1]]=tot=1;
    39         for (int i=2;i<=n;i++){
    40             if (y[SA[i]]!=y[SA[i-1]]||y[SA[i]+len]!=y[SA[i-1]+len]) tot++;
    41             x[SA[i]]=tot;    
    42         }
    43     }
    44     for (int i=1;i<=n;i++) rank[i]=x[i];
    45 }
    46 void get_height(){
    47     for (int i=1,j=0;i<=n;i++){
    48         if (rank[i]==1) continue;
    49         while (s[i+j]==s[SA[rank[i]-1]+j]) j++;
    50         height[rank[i]]=j;
    51         if (j>0) j--;
    52     }    
    53 }
    54 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    55 void merge(int x,int y){
    56     siz[y]+=siz[x];
    57     max_val[y]=max(max_val[y],max_val[x]);
    58     min_val[y]=min(min_val[y],min_val[x]);
    59     fa[x]=y;    
    60 }
    61 int main(){
    62     read(n);
    63     scanf("%s",s+1);
    64     get_SA(),get_height();
    65     for (int i=1;i<=n;i++) read(val[i]);
    66     for (int i=1;i<=n;i++) max_val[i]=val[SA[i]];
    67     for (int i=1;i<=n;i++) min_val[i]=val[SA[i]];
    68     for (int i=1;i<=n;i++) fa[i]=i;
    69     for (int i=1;i<=n;i++) siz[i]=1;
    70     for (int i=1;i<n;i++) list[i]=i+1;
    71     for (int i=1;i<=n;i++) ans[1][i]=-inf;
    72     sort(list+1,list+n,cmp);
    73     for (int i=1;i<n;i++){
    74         int x=find(list[i]-1),y=find(list[i]);
    75         ans[0][height[list[i]]]+=1LL*siz[x]*siz[y];
    76         ans[1][height[list[i]]]=max(ans[1][height[list[i]]],1LL*max_val[x]*max_val[y]);
    77         ans[1][height[list[i]]]=max(ans[1][height[list[i]]],1LL*max_val[x]*min_val[y]);
    78         ans[1][height[list[i]]]=max(ans[1][height[list[i]]],1LL*min_val[x]*max_val[y]);
    79         ans[1][height[list[i]]]=max(ans[1][height[list[i]]],1LL*min_val[x]*min_val[y]);
    80         merge(x,y);
    81     }
    82     for (int i=n-2;i>=0;i--) ans[0][i]+=ans[0][i+1],ans[1][i]=max(ans[1][i],ans[1][i+1]);
    83     for (int i=0;i<n;i++) printf("%lld %lld
    ",ans[0][i],ans[0][i]?ans[1][i]:0);
    84     return 0;
    85 }
  • 相关阅读:
    Crontab问题总结
    确定两个 Geometry 实例之间的关系
    Silverlight 多点触控(MultiTouch)
    在.NET中嵌入IronPython 交互
    Siebel集成OBI报表
    Silverlight XPS (PPT) Online
    Siebel Data Validation Manage 数据验证
    Siebel 附件清理
    Siebel 消息广播管理
    怎样创建一个.NET RIA Services Application (二)
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/4733941.html
Copyright © 2011-2022 走看看