zoukankan      html  css  js  c++  java
  • [BZOJ]4199: [Noi2015]品酒大会(后缀数组+笛卡尔树)

    Time Limit: 10 Sec  Memory Limit: 512 MB

    Description

    Input

    Output

    Sample Input

    10
    ponoiiipoi
    2 1 4 7 4 8 3 6 4 7

    Sample Output

    45 56
    10 56
    3 32
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0

    HINT

     

    Solution

      先求出后缀数组,两个后缀的最长公共前缀是它们之间height的最小值,对height建笛卡尔树,树上维护最大最小值即可。

    Code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    inline int read()
    {
        int x,f=1;char c;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=0;
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=x*10+c-'0';
        return f?x:-x;
    }
    #define MN 300000
    int v[MN+5],ar[MN*4+10],*sa=ar,*nsa=sa+MN+2,*rk=nsa+MN+2,*nrk=rk+MN+2,h[MN+5];
    int a[MN+5],z[MN+5],zn,lc[MN+5],rc[MN+5],sz[MN+5],mx[MN+5],mn[MN+5];
    ll f1[MN+5],f2[MN+5];
    char s[MN+5];
    void dfs(int x)
    {
        if(!x)return;
        int l=lc[x],r=rc[x];
        dfs(l);dfs(r);
        if(!l)l=MN+1,sz[l]=1,mx[l]=mn[l]=a[sa[x-1]];
        if(!r)r=MN+2,sz[r]=1,mx[r]=mn[r]=a[sa[x]];
        f1[h[x]]+=1LL*sz[l]*sz[r];
        f2[h[x]]=max(f2[h[x]],max(max(1LL*mn[l]*mn[r],1LL*mn[l]*mx[r]),
                                  max(1LL*mx[l]*mn[r],1LL*mx[l]*mx[r])));
        sz[x]=sz[l]+sz[r];
        mn[x]=min(mn[l],mn[r]);
        mx[x]=max(mx[l],mx[r]);
    }
    int main()
    {
        int n=read(),l,i,x;
        scanf("%s",s+1);
        for(i=1;i<=n;++i)a[i]=read();
        for(i=1;i<=n;++i)++v[s[i]];
        for(i='a';i<='z';++i)v[i]+=v[i-1];
        for(i=1;i<=n;++i)sa[v[s[i]]--]=i;
        for(i=1;i<=n;++i)rk[sa[i]]=rk[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]);
        for(l=1;l<n;l<<=1,swap(sa,nsa),swap(rk,nrk))
        {
            for(i=1;i<=n;++i)v[rk[sa[i]]]=i;
            for(i=n;i;--i)if(sa[i]>l)nsa[v[rk[sa[i]-l]]--]=sa[i]-l;
            for(i=0;i<l;++i)nsa[v[rk[n-i]]--]=n-i;
            for(i=1;i<=n;++i)nrk[nsa[i]]=nrk[nsa[i-1]]+(rk[nsa[i]]!=rk[nsa[i-1]]||rk[nsa[i]+l]!=rk[nsa[i-1]+l]);
        }
        for(i=1,l=0;i<=n;++i,l?--l:0)
            if(rk[i]>1){for(x=sa[rk[i]-1];s[i+l]==s[x+l];++l);h[rk[i]]=l;}
        for(i=2;i<=n;++i)
        {
            while(zn&&h[i]<h[z[zn]])lc[i]=z[zn--];
            rc[z[zn]]=i;z[++zn]=i;
        }
        memset(f2,200,sizeof(f2));
        dfs(z[1]);
        for(i=n;i--;)f1[i]+=f1[i+1],f2[i]=max(f2[i],f2[i+1]);
        for(i=0;i<n;++i)printf("%lld %lld
    ",f1[i],f1[i]?f2[i]:0);
    }
  • 相关阅读:
    C# WinForm TreeView改变选中节点颜色,失去焦点选中节点仍突显
    TextBox的ReadOnly属性设置为True后获取不到值
    如何设置打印机共享
    细节啊,不注意真是会很纠结
    设置access类型
    未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序
    带关闭的漂浮广告
    图片添加热点
    使用 WebDeploymentSetup VS 2010 Web项目部署
    动态操作表格
  • 原文地址:https://www.cnblogs.com/ditoly/p/BZOJ4199.html
Copyright © 2011-2022 走看看