bzoj4199 [Noi2015]品酒大会

题面:见uoj

 

正解:后缀自动机+后缀树+树形$dp$。

好像这题正解是后缀数组来着,然而用后缀自动机就简单多了。。

反串构出后缀树,然后直接树形$dp$即可,注意最大答案可能是最小值与最小值的乘积。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define Inf (1000000007)
 6 #define inf (1LL<<60)
 7 #define N (600010)
 8 
 9 using namespace std;
10 
11 struct edge{ int nt,to; }g[N<<1];
12 
13 int ch[N][26],fa[N],l[N],sz[N],Mx[N],Mn[N],val[N],head[N],a[N],n,la,tot,len,num;
14 ll sum[N],res[N];
15 char s[N];
16 
17 il int gi(){
18   RG int x=0,q=1; RG char ch=getchar();
19   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
20   if (ch=='-') q=-1,ch=getchar();
21   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
22   return q*x;
23 }
24 
25 il void insert(RG int from,RG int to){
26   g[++num]=(edge){head[from],to},head[from]=num; return;
27 }
28 
29 il void add(RG int c){
30   RG int p=la,np=++tot; la=np,l[np]=l[p]+1,sz[np]=1;
31   for (;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
32   if (!p){ fa[np]=1; return; } RG int q=ch[p][c];
33   if (l[q]==l[p]+1) fa[np]=q; else{
34     RG int nq=++tot; l[nq]=l[p]+1,val[nq]=-Inf;
35     fa[nq]=fa[q],fa[q]=fa[np]=nq;
36     memcpy(ch[nq],ch[q],sizeof(ch[q]));
37     for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
38   }
39   return;
40 }
41 
42 il void dfs(RG int x){
43   Mx[x]=Mn[x]=val[x];
44   for (RG int i=head[x],v;i;i=g[i].nt){
45     v=g[i].to,dfs(v),sum[l[x]]+=1LL*sz[x]*sz[v],sz[x]+=sz[v];
46     if (Mx[x]!=-Inf && Mx[v]!=-Inf) res[l[x]]=max(res[l[x]],1LL*Mx[x]*Mx[v]);
47     if (Mn[x]!=-Inf && Mn[v]!=-Inf) res[l[x]]=max(res[l[x]],1LL*Mn[x]*Mn[v]);
48     Mx[x]=max(Mx[x],Mx[v]),Mn[x]=min(Mn[x],Mn[v]); if (Mn[x]==-Inf) Mn[x]=Mn[v];
49   }
50   return;
51 }
52 
53 int main(){
54 #ifndef ONLINE_JUDGE
55   freopen("savour.in","r",stdin);
56   freopen("savour.out","w",stdout);
57 #endif
58   n=gi(),scanf("%s",s+1),len=strlen(s+1),val[la=++tot]=-Inf;
59   for (RG int i=1;i<=n;++i) a[i]=gi(),res[i]=-inf; res[0]=-inf;
60   for (RG int i=len;i;--i) add(s[i]-'a'),val[la]=a[i];
61   for (RG int i=2;i<=tot;++i) insert(fa[i],i); dfs(1);
62   for (RG int i=n-1;i>=0;--i) sum[i]+=sum[i+1],res[i]=max(res[i],res[i+1]);
63   for (RG int i=0;i<n;++i) printf("%lld %lld\n",sum[i],sum[i] ? res[i] : 0);
64   return 0;
65 }

 

posted @ 2017-10-06 13:37  wfj_2048  阅读(194)  评论(0编辑  收藏  举报