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

    来自FallDream的博客,未经允许,请勿转载,谢谢

    n<=3*10^5

    有一道题很类似 我写了两种做法 戳这里

    这道理也可以类似做,建出笛卡尔树之后维护子树最大最小值(负负得正)就行了

    没判负负得正爆了一次。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MN 300000
    #define N 524288
    #define ll long long
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
     
    char st[MN*2+5];
    int v[MN+5],n,H[MN+5],s[MN+5],S[MN+5],size[MN+5],p=1,q=0,k=1;
    int sa[2][MN+5],rk[2][MN+5],Q[MN+5],top=0,L[MN+5],R[MN+5],mx[MN+5],mx2[MN+5],lt[MN+5],mn[MN+5],mn2[MN+5];
    ll Ans[MN+5],Mx[MN+5];
     
    void CalcSA(int*SA,int*RK,int*sa,int*rk)
    {   
        for(int i=1;i<=n;++i) v[rk[sa[i]]]=i;
        for(int i=n;i;--i)
            if(sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k;
        for(int i=n-k+1;i<=n;++i) SA[v[rk[i]]--]=i;
        for(int i=1;i<=n;++i) RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]);
    }
     
    void GetH(int*sa,int*rk)
    {
        for(int i=1,k=0;i<=n;H[rk[i++]]=k,k==0?0:--k) if(rk[i]!=1)
            for(int j=sa[rk[i]-1];st[j+k]==st[i+k];++k);
    }
     
    int Build()
    {
        for(int i=2;i<=n;++i)    
        {
            int last=0;
            while(top&&H[Q[top]]>=H[i]) last=Q[top--];
            if(top) R[Q[top]]=i;
            L[Q[++top]=i]=last;         
        }
        return Q[1];
    }
     
    inline void Up(int&a,int&b,int c)
    {
        if(c>a) b=a,a=c;
        else if(c>b) b=c;    
    }
     
    inline void UP(int&a,int&b,int c)
    {
        if(c<a) b=a,a=c;
        else if(c<b) b=c;    
    }
     
    void Dfs(int x)
    {   
        lt[x]=S[x-1];
        if(L[x]) Dfs(L[x]),lt[x]=lt[L[x]];  
        if(R[x]) Dfs(R[x]);
        size[x]=size[L[x]]+size[R[x]]+1;    
        Up(mx[x],mx2[x],S[x]);
        UP(mn[x],mn2[x],S[x]);
        if(L[x])Up(mx[x],mx2[x],mx[L[x]]),
        Up(mx[x],mx2[x],mx2[L[x]]),
        UP(mn[x],mn2[x],mn[L[x]]),
        UP(mn[x],mn2[x],mn2[L[x]]);
        if(R[x])Up(mx[x],mx2[x],mx[R[x]]),
        Up(mx[x],mx2[x],mx2[R[x]]),
        UP(mn[x],mn2[x],mn[R[x]]),
        UP(mn[x],mn2[x],mn2[R[x]]);
        Ans[H[x]]+=1LL*(size[L[x]]+1)*(size[R[x]]+1);
        Mx[H[x]]=max(Mx[H[x]],1LL*mx[x]*max(lt[x],mx2[x]));
        if(mn[x]<=0&&min(mn2[x],lt[x])<=0)
        Mx[H[x]]=max(Mx[H[x]],1LL*mn[x]*min(mn2[x],lt[x]));
    }
     
    int main()
    {
        memset(Mx,128,sizeof(Mx));
        memset(mx,128,sizeof(mx));
        memset(mx2,128,sizeof(mx2));
        memset(mn,127,sizeof(mn));
        memset(mn2,127,sizeof(mn2));
        n=read();scanf("%s",st+1);
        for(int i=1;i<=n;++i) s[i]=read();
        for(int i=1;i<=n;++i) ++v[st[i]-'a'];
        for(int i=1;i<26;++i) v[i]+=v[i-1];
        for(int i=1;i<=n;++i) sa[q][v[st[i]-'a']--]=i;
        for(int i=1;i<=n;++i) rk[q][sa[q][i]]=rk[q][sa[q][i-1]]+(st[sa[q][i]]!=st[sa[q][i-1]]);
        for(k=1;k<n;k<<=1)
        {
            CalcSA(sa[p],rk[p],sa[q],rk[q]);
            swap(p,q);
        }
        GetH(sa[q],rk[q]);
        for(int i=1;i<=n;++i) S[rk[q][i]]=s[i];
        int rt=Build();Dfs(rt);
        for(int i=n-1;~i;--i) Mx[i]=max(Mx[i],Mx[i+1]),Ans[i]+=Ans[i+1];
        for(int i=0;i<n;++i) printf("%lld %lld
    ",Ans[i],!Ans[i]?0:Mx[i]); 
        return 0;
    }
  • 相关阅读:
    九连环
    Fruit Ninja(取随机数)
    Distinct Values(贪心)
    Harvest of Apples
    Don't Be a Subsequence
    ConvexScore
    守卫
    Trie树
    NOIP 2005 过河
    HDU 4597 Play Game 记忆化DP
  • 原文地址:https://www.cnblogs.com/FallDream/p/Noi2015d2t2.html
Copyright © 2011-2022 走看看