题目大意:略
40分暴力还是很好写的,差分再跑个后缀和 和 后缀最大值就行了
一种正解是后缀数组+并查集
但据说还有后缀数组+单调栈的高端操作蒟蒻的我当然不会
后缀数组求出height,然后从大到小排个序,那么每次把最大height的两个后缀放到一个并查集里
这样,每次根据height合并两个并查集的时候,一个并查集任何一个后缀和另一个并查集任何一个后缀的LCP长度都是height[i]
并查集维护集合内a[i]最大值,最小值(负负得正),然后每次合并都打差分,统计答案的时候跑一遍后缀和和后缀最大值即可
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define ll long long 6 #define N 301000 7 #define rint register int 8 #define inf 1000000000000000001ll 9 using namespace std; 10 //re 11 int len; 12 char str[N]; 13 int tr[N],rk[N],hs[N],sa[N],fa[N]; 14 ll a[N],ma[N],mi[N],ans[N],sum[N],p[N],sz[N]; 15 struct Height{int id,w;}h[N]; 16 int cmp(Height s1,Height s2){return s1.w>s2.w;} 17 bool check(int k,int x,int y){ 18 if(x+k>len||y+k>len) return 0; 19 else return (rk[x]==rk[y]&&rk[x+k]==rk[y+k])?1:0; 20 } 21 void get_sa() 22 { 23 int cnt=0;rint i; 24 for(i=1;i<=len;++i) hs[str[i]]++; 25 for(i=1;i<=127;++i) if(hs[i]) tr[i]=++cnt; 26 for(i=1;i<=127;++i) hs[i]+=hs[i-1]; 27 for(i=1;i<=len;++i) rk[i]=tr[str[i]],sa[hs[str[i]]--]=i; 28 for(int k=1;cnt<len;k<<=1) 29 { 30 for(i=1;i<=cnt;++i) hs[i]=0; 31 for(i=1;i<=len;++i) hs[rk[i]]++; 32 for(i=1;i<=cnt;++i) hs[i]+=hs[i-1]; 33 for(i=len;i>=1;i--) if(sa[i]>k) tr[sa[i]-k]=hs[rk[sa[i]-k]]--; 34 for(i=1;i<=k;++i) tr[len-i+1]=hs[rk[len-i+1]]--; 35 for(i=1;i<=len;++i) sa[tr[i]]=i; 36 for(i=1,cnt=0;i<=len;++i) tr[sa[i]]=check(k,sa[i],sa[i-1])?cnt:++cnt; 37 for(i=1;i<=len;++i) rk[i]=tr[i]; 38 } 39 for(i=1;i<=len;++i){ 40 h[i].id=i; 41 if(rk[i]==1) continue; 42 for(int j=max(1,h[rk[i-1]].w-1);;j++) 43 if(str[i+j-1]==str[sa[rk[i]-1]+j-1]) h[rk[i]].w=j; 44 else break; 45 } 46 } 47 int find_fa(int x){ 48 int y=x; 49 while(y!=fa[y]) y=fa[y]; 50 while(fa[x]!=y){ 51 int pre=fa[x]; 52 fa[x]=y; 53 x=pre; 54 }return y; 55 } 56 void solve() 57 { 58 rint i;int x,y,fx,fy; 59 for(i=1;i<=len;++i) sz[i]=1,fa[i]=i,mi[i]=ma[i]=a[sa[i]]; 60 for(i=1;i<=len;) 61 { 62 int j=h[i].w; 63 for(;h[i].w>=j&&i<=len;i++){ 64 x=h[i].id-1;fx=find_fa(x); 65 y=h[i].id;fy=find_fa(y); 66 p[j]+=sz[fx]*sz[fy]; 67 ans[j]=max(ans[j],max(mi[fx]*mi[fy],ma[fx]*ma[fy])); 68 fa[fy]=fx,sz[fx]+=sz[fy]; 69 ma[fx]=max(ma[fx],ma[fy]),mi[fx]=min(mi[fx],mi[fy]); 70 } 71 } 72 } 73 74 int main() 75 { 76 scanf("%d",&len); 77 scanf("%s",str+1); 78 for(int i=1;i<=len;++i) 79 scanf("%lld",&a[i]); 80 memset(ans,-0x3f,sizeof(ans)); 81 get_sa(); 82 sort(h+1,h+len+1,cmp); 83 solve(); 84 for(int i=len;i>=0;i--) 85 sum[i]=sum[i+1]+p[i],ans[i]=max(ans[i],ans[i+1]); 86 for(int i=0;i<len;i++) 87 printf("%lld %lld ",sum[i],(ans[i]<=-inf)?0:ans[i]); 88 return 0; 89 }