记录编号 284169 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2015]品酒大会 最终得分 100
用户昵称 GravatarTenderRun 是否通过 通过
代码语言 C++ 运行时间 1.933 s
提交时间 2016-07-17 13:10:26 内存使用 106.17 MiB
显示代码纯文本
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=600010;
const long long INF=1LL<<60;
int n,cnt,last,ord[maxn],c[maxn];
int fa[maxn],ch[maxn][26],len[maxn];
long long tmp[maxn],mx[maxn],mn[maxn],w[maxn];
long long num[maxn],tot[maxn],t1[maxn],t2[maxn];
char s[maxn];

struct SAM{
	SAM(){cnt=last=1;}
	void Insert(int c,int t){
		int p=last,np=last=++cnt;tmp[np]=1;
		len[np]=len[p]+1;mx[cnt]=mn[cnt]=w[t];
		while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
		if(!p)fa[np]=1;
		else{
			int q=ch[p][c],nq;
			if(len[q]==len[p]+1)
				fa[np]=q;
			else{
				len[nq=++cnt]=len[p]+1;
				mx[cnt]=-INF;mn[cnt]=INF;
				memcpy(ch[nq],ch[q],sizeof(ch[q]));
				fa[nq]=fa[q];fa[q]=fa[np]=nq;
				while(ch[p][c]==q)ch[p][c]=nq,p=fa[p];
			}
		}
		return; 
	}
	
	void Solve(){
		for(int i=1;i<=cnt;i++)c[len[i]]++;
		for(int i=1;i<=len[last];i++)c[i]+=c[i-1];
		for(int i=1;i<=cnt;i++)ord[c[len[i]]--]=i;
		for(int i=1;i<=cnt;i++)t2[i]=num[i]=-INF;
		mn[1]=INF;mx[1]=-INF;
		
		for(int i=cnt;i>=1;i--){
			int p=ord[i];
			t1[fa[p]]+=tmp[fa[p]]*tmp[p];
			tmp[fa[p]]+=tmp[p];
			if(mn[fa[p]]!= INF)t2[fa[p]]=max(t2[fa[p]],mn[p]*mn[fa[p]]);
			if(mx[fa[p]]!=-INF)t2[fa[p]]=max(t2[fa[p]],mx[p]*mx[fa[p]]);
			mn[fa[p]]=min(mn[fa[p]],mn[p]);
			mx[fa[p]]=max(mx[fa[p]],mx[p]);
		}
		
		for(int i=1;i<=cnt;i++){
			tot[len[i]]+=t1[i];
			num[len[i]]=max(num[len[i]],t2[i]);
		}
		
		for(int i=n-2;i>=0;i--){
			tot[i]+=tot[i+1];
			num[i]=max(num[i],num[i+1]);
		}
		
		for(int i=0;i<n;i++)
			printf("%lld %lld\n",tot[i],tot[i]?num[i]:0);
	}
}sam;

int main(){
	freopen("savour.in","r",stdin);
	freopen("savour.out","w",stdout);
	scanf("%d%s",&n,s);
	for(int i=1;i<=n;i++)scanf("%lld",&w[i]);
	for(int i=n;i;i--)sam.Insert(s[i-1]-'a',i);
	sam.Solve();	
	return 0;
}