记录编号 389177 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2015]品酒大会 最终得分 100
用户昵称 Gravatarwumingshi 是否通过 通过
代码语言 C++ 运行时间 1.971 s
提交时间 2017-03-30 20:05:05 内存使用 23.47 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=300010;
struct edge
{
	int nxt,to;
}a[N];
ll ans[N],Max[N],Min[N],tot[N],size[N];
char s[N];
int t1[N],t2[N],sa[N],height[N],rank[N],c[N],f[N],head[N];
int n,num,lv;
inline ll max(ll a,ll b){return a>b?a:b;}
inline ll min(ll a,ll b){return a<b?a:b;}
inline void add(int x,int y)
{
	a[++num].nxt=head[x],a[num].to=y,head[x]=num;
}
int find(int n)
{
	if(f[n]!=n) f[n]=find(f[n]);
	return f[n];
}
inline bool cmp(int *y,int a,int b,int k)
{
	int r1=y[a],r2=y[b];
	int r3=a+k>=n?-1:y[a+k];
	int r4=b+k>=n?-1:y[b+k];
	return r1==r2&&r3==r4;
}
inline void makesa()
{
	int *x=t1,*y=t2,m=30;
	for(int i=0;i<m;i++) c[i]=0;
	for(int i=0;i<n;i++) c[x[i]=s[i]-'a']++;
	for(int i=1;i<m;i++) c[i]+=c[i-1];
	for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
	for(int k=1;k<=n;k<<=1)
	{
		int p=0;
		for(int i=n-k;i<n;i++) y[p++]=i;
		for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
		for(int i=0;i<m;i++) c[i]=0;
		for(int i=0;i<n;i++) c[x[y[i]]]++;
		for(int i=1;i<m;i++) c[i]+=c[i-1];
		for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
		swap(x,y);
		p=1;x[sa[0]]=0;
		for(int i=1;i<n;i++)
		  x[sa[i]]=cmp(y,sa[i],sa[i-1],k)?p-1:p++;
		if(p>=n) break;
		m=p;
	}
}
inline void makeheight()
{
	for(int i=0;i<n;i++) rank[sa[i]]=i;
	int k=0;
	for(int i=0;i<n;i++)
	  if(rank[i])
	  {
	  	int j=sa[rank[i]-1];
	  	if(k) k--;
	  	while(s[i+k]==s[j+k]) k++;
	  	height[rank[i]]=k;
	  }
}
inline void merge(int i,int x,int y)
{
	f[y]=x;
	ans[i]=max(ans[i],Max[sa[x]]*Max[sa[y]]);
	ans[i]=max(ans[i],Min[sa[x]]*Min[sa[y]]);
	Max[sa[x]]=max(Max[sa[x]],Max[sa[y]]);
	Min[sa[x]]=min(Min[sa[x]],Min[sa[y]]);
	tot[i]+=size[sa[x]]*size[sa[y]];
	size[sa[x]]+=size[sa[y]];
}
inline void solve()
{
	for(int i=1;i<n;i++)
	  add(height[i],i);
	for(int i=n-1;i>=0;i--)
	  for(int j=head[i];j;j=a[j].nxt)
	  {
		int x=find(a[j].to),y=find(a[j].to-1);
		merge(i,x,y);
	  }
	for(int i=n-2;i>=0;i--)
	  tot[i]+=tot[i+1],ans[i]=max(ans[i],ans[i+1]);
	for(int i=0;i<n;i++)
	  if(tot[i]) printf("%lld %lld\n",tot[i],ans[i]);
	  else printf("0 0\n");
}
int main()
{
	freopen("savour.in","r",stdin);
	freopen("savour.out","w",stdout);
	scanf("%d",&n);
	scanf("%s",s);
	for(int i=0;i<n;i++)
	  scanf("%d",&lv),f[i]=i,Max[i]=Min[i]=lv,size[i]=1,ans[i]=-1e18;
	makesa();
	makeheight();
	solve();
	return 0;
}