noi2015品酒大会(sa)

用常用的套路,排序之后从大到小插入height,用并查集维护即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=300010;
const ll inf=1e18;
int n,sa[maxn],H[maxn],ra[maxn],tong[maxn],m,tp[maxn],fa[maxn];
ll ans1[maxn],ans2[maxn],c[maxn];
char s[maxn]; 
int getfa(int x){return (x==fa[x])?x:fa[x]=getfa(fa[x]);}
void rsort(){
    for(int i=0;i<=m;++i)tong[i]=0;
    for(int i=1;i<=n;++i)tong[ra[tp[i]]]++;
    for(int i=1;i<=m;++i)tong[i]+=tong[i-1];
    for(int i=n;i>=1;--i)sa[tong[ra[tp[i]]]--]=tp[i];
}
int cmp(int x,int y,int w){return tp[x]==tp[y]&&tp[x+w]==tp[y+w];}
void pre(){
    for(int i=1;i<=n;++i)ra[i]=s[i]-'a'+1,tp[i]=i;
    
    m=32;rsort();
    
    for(int w=1,p=1,i;p<n;w+=w,m=p){
        for(p=0,i=n-w+1;i<=n;++i)tp[++p]=i;
        for(i=1;i<=n;++i)if(sa[i]>w)tp[++p]=sa[i]-w;
        rsort();swap(tp,ra);ra[sa[1]]=p=1;
        for(i=2;i<=n;++i)ra[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
    }
    int j,k=0;
    for(int i=1;i<=n;H[ra[i++]]=k)
        for(k=k?k-1:k,j=sa[ra[i]-1];s[i+k]==s[j+k];++k);
}
struct node{
    int id,v;
    bool operator<(const node&t)const{
        return v<t.v;
    }
}tmp[maxn];
struct lian{
    int l,r;
    ll ma,mi,len;
}a[maxn];
void merge(int x,int y,int w){
    x=getfa(x);y=getfa(y);
    ll t1=max(a[x].ma*a[y].ma,a[x].mi*a[y].mi);
    ll t2=max(a[x].ma*a[y].mi,a[x].mi*a[y].ma);
    ll t3=min(a[x].ma*a[y].ma,a[x].mi*a[y].mi);
    ll t4=min(a[x].ma*a[y].mi,a[x].mi*a[y].ma);
    a[x].ma=max(a[x].ma,a[y].ma);
    a[x].mi=min(a[y].mi,a[x].mi);
    ans1[w]+=a[x].len*a[y].len;
    a[x].len+=a[y].len;
    fa[y]=x;
    ans2[w]=max(ans2[w],max(t1,t2));
    
}
int main(){
    cin>>n;
    scanf("%s",s+1);
    pre();
    for(int i=1;i<=n;++i){
        tmp[i-1].id=i,tmp[i-1].v=H[i];
    }
    sort(tmp+1,tmp+n);
    for(int i=1;i<=n;++i)scanf("%lld",&c[i]);
    for(int i=1;i<=n;++i){
        a[i].mi=a[i].ma=c[sa[i]];
        a[i].l=a[i].r=i;a[i].len=1;
        fa[i]=i;
    }
    //for(int i=1;i<=n;++i)cout<<sa[i]<<' '<<H[i]<<endl;
    for(int i=0;i<=n;++i)ans2[i]=-inf;
    for(int i=n-1;i>=1;--i){
        merge(tmp[i].id-1,tmp[i].id,tmp[i].v);
    }
    for(int i=n-2;i>=0;--i){
        ans1[i]+=ans1[i+1];
        ans2[i]=max(ans2[i],ans2[i+1]);
    }
    for(int i=0;i<=n-1;++i){
        printf("%lld ",ans1[i]);
        if(ans2[i]==-inf)printf("%lld
",0);
        else printf("%lld
",ans2[i]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dibaotianxing/p/8453699.html