记录编号 220615 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2015]品酒大会 最终得分 100
用户昵称 Gravatar神利·代目 是否通过 通过
代码语言 C++ 运行时间 5.572 s
提交时间 2016-01-19 17:26:56 内存使用 106.35 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
inline long long MAX(long long A,long long B){return A>B?A:B;}
int n,c[310000],w[310000];
struct SAM
{
	int cnt,tail;
	struct node{int son[26],fa,len;bool flag;}o[610000];
	void add(int x)
	{
		int p,np=++cnt,q,nq;
		o[np].len=o[tail].len+1;
		o[np].flag=1;
		for(p=tail;p&&!o[p].son[x];p=o[p].fa)
			o[p].son[x]=np;
		if(!o[p].son[x])
			o[p].son[x]=np;
		else
		{
			q=o[p].son[x];
			if(o[q].len==o[p].len+1)
				o[np].fa=q;
			else
			{
				o[nq=++cnt]=o[q];
				o[nq].flag=0;
				o[q].fa=o[np].fa=nq;
				o[nq].len=o[p].len+1;
				for(;o[p].son[x]==q;p=o[p].fa)
					o[p].son[x]=nq;
			}
		}
		tail=np;
	}
}sam;
int shu,first[610000];
struct edge
{
	int v,nx;
}o[610000];
inline void add(int u,int v)
{
	o[++shu].v=v;
	o[shu].nx=first[u];
	first[u]=shu;
}
int L,R;
long long X,ans1[310000],t1[1210000];
inline void pushdown1(int t)
{
	t1[t<<1]+=t1[t];
	t1[t<<1|1]+=t1[t];
	t1[t]=0;
}
inline void ADD(int l,int r,int t)
{
	if(L<=l&&r<=R)
	{
		t1[t]+=X;
		return;
	}
	if(t1[t])
		pushdown1(t);
	int mid=l+r>>1;
	if(mid>=L)
		ADD(l,mid,t<<1);
	if(mid<R)
		ADD(mid+1,r,t<<1|1);
}
long long ans2[310000],t2[1210000];
inline void pushdown2(int t)
{
	t2[t<<1]=MAX(t2[t<<1],t2[t]);
	t2[t<<1|1]=MAX(t2[t<<1|1],t2[t]);
	t2[t]=-1e18;
}
inline void change(int l,int r,int t)
{
	if(L<=l&&r<=R)
	{
		t2[t]=MAX(t2[t],X);
		return;
	}
	if(t2[t]>-1e18)
		pushdown2(t);
	int mid=l+r>>1;
	if(mid>=L)
		change(l,mid,t<<1);
	if(mid<R)
		change(mid+1,r,t<<1|1);
}
int s[610000],max[610000][2],min[610000][2];
inline void dfs(int x)
{
	if(sam.o[x].flag)
	{
		++s[x];		
		max[x][0]=min[x][0]=w[n-sam.o[x].len+1];
	}
	for(int i=first[x];i;i=o[i].nx)
	{
		dfs(o[i].v);
		s[x]+=s[o[i].v];
		if(max[o[i].v][1]>=max[x][0])
		{
			max[x][0]=max[o[i].v][0];
			max[x][1]=max[o[i].v][1];
		}
		else if(max[o[i].v][0]>=max[x][0]&&max[o[i].v][1]<=max[x][0])
		{
			max[x][1]=max[x][0];			
			max[x][0]=max[o[i].v][0];
		}
		else if(max[o[i].v][0]>max[x][1])
			max[x][1]=max[o[i].v][0];
		if(min[o[i].v][1]<=min[x][0])
		{
			min[x][0]=min[o[i].v][0];
			min[x][1]=min[o[i].v][1];
		}
		else if(min[o[i].v][0]<=min[x][0]&&min[o[i].v][1]>=min[x][0])
		{
			min[x][1]=min[x][0];			
			min[x][0]=min[o[i].v][0];
		}
		else if(min[o[i].v][0]<min[x][1])
			min[x][1]=min[o[i].v][0];
	}
	X=(long long)s[x]*(s[x]-1)>>1;
	L=sam.o[sam.o[x].fa].len+1,R=sam.o[x].len;
	if(L<=R)
		ADD(0,n,1);
	if(s[x]>1)
	{
		X=(long long)max[x][0]*max[x][1];
		if(X<(long long)min[x][0]*min[x][1])
			X=(long long)min[x][0]*min[x][1];
		L=0,R=sam.o[x].len;
		change(0,n,1);
	}
}
inline void find(int l,int r,int t)
{
	if(l==r)
	{
		ans1[l]=t1[t];
		return;
	}
	if(t1[t])
		pushdown1(t);
	int mid=l+r>>1;
	find(l,mid,t<<1);
	find(mid+1,r,t<<1|1);
}
inline void DFS(int l,int r,int t)
{
	if(l==r)
	{
		ans2[l]=t2[t];
		return;
	}
	if(t2[t]>-1e18)
		pushdown2(t);
	int mid=l+r>>1;
	DFS(l,mid,t<<1);
	DFS(mid+1,r,t<<1|1);
}
int main()
{
	freopen("savour.in","r",stdin);
	freopen("savour.out","w",stdout);
	memset(max,-0x3f,sizeof(max));
	memset(min,0x3f,sizeof(min));
	memset(t2,-0x3f,sizeof(t2));
	memset(ans2,-0x7f,sizeof(ans2));
	c[++n]=getchar();
	while(c[n]<'a'||c[n]>'z')
		c[n]=getchar();
	while('a'<=c[n]&&c[n]<='z')
		c[++n]=getchar();
	--n;
	for(int i=n;i;--i)
		sam.add(c[i]-97);
	long long Max1=-0x7fffffff,Max2=-0x7fffffff,Min1=0x7fffffff,Min2=0x7fffffff;
	for(int i=1;i<=n;++i)
	{
		scanf("%d",&w[i]);
		if(Max1<w[i])
		{
			Max2=Max1;
			Max1=w[i];
		}
		else if(Max2<w[i])
			Max2=w[i];
		if(Min1>w[i])
		{
			Min2=Min1;
			Min1=w[i];
		}
		else if(Min2>w[i])
			Min2=w[i];	
	}
	ans2[0]=Max1*Max2;
	if(ans2[0]<Min1*Min2)
		ans2[0]=Min1*Min2;
	for(int i=1;i<=sam.cnt;++i)
		add(sam.o[i].fa,i);
	dfs(0);
	find(0,n,1);
	DFS(0,n,1);
	ans1[0]=(long long)n*(n-1)>>1;
	for(int i=0;i<n;++i)
		if(ans2[i]<=-1e18)
			ans2[i]=0;
	for(int i=0;i<n;++i)
		printf("%lld %lld\n",ans1[i],ans2[i]);
}